Вопрос с собеседования · DevOps

Как написать хороший Dockerfile?

MiddleDocker и контейнерыDocker
Ещё спрашивают так:
  • Что такое multi-stage build?
  • Как уменьшить размер Docker-образа и ускорить сборку?
Коротко

Multi-stage: собирать в образе с компиляторами, а в финальный копировать только артефакт — образ в разы меньше. Порядок инструкций под кэш: сначала то, что меняется редко (зависимости), потом код. Маленький базовый образ (slim, distroless, alpine — с оговорками), не root, фиксированные версии, .dockerignore, exec-форма CMD для корректных сигналов.

  • COPY package*.json и npm ci до COPY . — зависимости кэшируются
  • Секреты не передавать через ARG/ENV — они остаются в слоях; использовать BuildKit secrets
  • Один процесс на контейнер

А ещё alpine на musl иногда даёт сюрпризы с бинарными зависимостями Python и glibc-софтом

Подробно

Размер и безопасность. Компилятор, менеджеры пакетов и исходники в рабочем образе не нужны — это мегабайты и лишние уязвимости. Distroless образы содержат только рантайм.

Кэш слоёв. Каждая инструкция — слой. Если слой изменился, все следующие пересобираются. Поэтому зависимости устанавливают отдельно от кода: изменение строчки кода не скачивает заново все библиотеки.

Прочее:

  • фиксировать версию базового образа (тег или digest), не latest;
  • объединять apt-get update && apt-get install … && rm -rf /var/lib/apt/lists/* в одну инструкцию;
  • .dockerignore — не тащить .git, node_modules, секреты в контекст сборки;
  • HEALTHCHECK или пробы оркестратора;
  • сканирование образов на уязвимости (Trivy) в CI.

Пример

# сборка
FROM eclipse-temurin:21-jdk AS build
WORKDIR /src
COPY gradle gradle
COPY gradlew build.gradle settings.gradle ./
RUN ./gradlew dependencies --no-daemon      # слой зависимостей кэшируется
COPY src src
RUN ./gradlew bootJar --no-daemon

# запуск
FROM eclipse-temurin:21-jre
RUN useradd --system app
USER app
COPY --from=build /src/build/libs/app.jar /app/app.jar
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75", "-jar", "/app/app.jar"]

Что хотят услышать

  • Multi-stage и маленький базовый образ.
  • Порядок инструкций и кэш.
  • Безопасность: не root, секреты, версии.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Копировать весь код до установки зависимостей, брать базовый образ с тегом latest и оставлять компиляторы в финальном образе на случай отладки
  • ✓Multi-stage сборка, порядок инструкций под кэш, маленький базовый образ, не root, фиксированные версии, exec-форма CMD
  • ✗Тег latest для базового образа — лучший выбор
  • ✗Компиляторы стоит оставлять в финальном образе

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования