← Назад к списку
ПрограммированиеDevOps и SREMiddle

Напишите production-готовый Dockerfile для Python-приложения. Объясните, как уменьшить образ и ускорить сборку за счёт кэша слоёв.

Короткий ответ

  • Multi-stage: зависимости собираются отдельно от runtime-образа
  • Сначала копировать файл зависимостей, потом код — ради кэша
  • Базовый образ slim и фиксированная версия тега
  • Запуск от непривилегированного пользователя
  • Меньше слоёв с мусором: no-cache-dir, очистка apt-списков
  • HEALTHCHECK и exec-форма CMD для корректных сигналов

Хороший Dockerfile — это multi-stage, правильный порядок слоёв под кэш, минимальный базовый образ и запуск не от root.

Как сказать вслух

пример ответа

Я делаю сборку в два этапа: в первом ставлю зависимости, во второй, чистый образ, копирую только результат. Файл с зависимостями копирую раньше кода, чтобы кэш слоёв не сбрасывался на каждый коммит. Беру slim-образ с зафиксированной версией, создаю отдельного пользователя и запускаю приложение не от root. В конце добавляю healthcheck и пишу CMD в exec-форме, чтобы процесс корректно получал сигналы остановки.

Подробный ответ

Основной ответ

Ключевые приёмы: multi-stage отделяет сборочные инструменты (компиляторы, dev-заголовки) от runtime; порядок инструкций использует кэш — зависимости меняются реже кода, поэтому COPY requirements и установка идут до COPY исходников; базовый образ python:slim с точным тегом вместо latest; непривилегированный пользователь (USER) снижает последствия компрометации; .dockerignore исключает .git, кэши и тесты; pip с --no-cache-dir не тащит кэш в слой. CMD в exec-форме делает процесс PID 1 и доставляет SIGTERM для graceful shutdown. Дальнейшее уменьшение — distroless-образы; проверка — сканеры уязвимостей (trivy) в CI.

Ключевые моменты

  • Кэш слоёв. Инструкции упорядочены от редко меняющихся к частым; изменение кода не инвалидирует слой с зависимостями.
  • Multi-stage. В финальный образ попадает только нужное для запуска — меньше размер и поверхность атаки.
  • Не root. USER с выделенным uid — базовая гигиена; многие кластеры запрещают root через политики.
  • Сигналы и PID 1. Exec-форма CMD без оболочки позволяет приложению получать SIGTERM и завершаться корректно.

Практический контекст

Типичное практическое задание: дают «плохой» Dockerfile и просят улучшить, либо написать свой с нуля. В работе от качества образа зависят скорость CI, время деплоя и результаты security-сканов. Интервьюер смотрит на порядок слоёв, multi-stage, пользователя и на то, может ли кандидат объяснить каждый приём, а не воспроизвести заготовку.

Пример кода

FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

FROM python:3.12-slim
WORKDIR /app
RUN useradd --create-home --uid 10001 appuser
COPY --from=builder /install /usr/local
COPY src/ ./src
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=3s \
  CMD python -c "import urllib.request;urllib.request.urlopen('http://127.0.0.1:8000/healthz')"
CMD ["gunicorn", "-b", "0.0.0.0:8000", "src.app:app"]

Частые ошибки

  • Копируют весь код до установки зависимостей, убивая кэш слоёв
  • Оставляют запуск от root и тег latest у базового образа
  • Используют shell-форму CMD, из-за чего приложение не получает SIGTERM

ИП Кочкин Алексей Сергеевич · ИНН 390509026279 · ОГРНИП 325390000030973 · jiniys2005@yandex.ru