Раздел 5. Dockerfile
Dockerfile — это не скрипт установки. Это описание того, как из базового образа получить новый набор слоёв, и одновременно описание того, как запускать полученный образ. Разница принципиальна: скрипт выполняется целиком каждый раз, а Dockerfile выполняется через кэш, и порядок инструкций напрямую определяет, будет ли сборка занимать три секунды или три минуты.
Раздел разбирает все инструкции по единому шаблону: назначение, синтаксис, пример, типичная ошибка и случаи, когда инструкцию применять не следует. Затем переходит к механике: как устроен build cache, что именно его инвалидирует, что даёт BuildKit (cache mounts, secret mounts, параллельная сборка стадий) и как multi-stage builds позволяют собрать приложение в одном окружении, а поставить — в другом.
Материал раздела нейтрален к языку. Применение к Python — в разделе 06.
Цели обучения
После раздела учащийся сможет:
- объяснить, что такое build context, и сократить его через
.dockerignore; - применять все базовые инструкции
Dockerfileпо назначению и объяснять, почему выбрана именно эта; - различать exec form и shell form и предсказывать поведение каждой;
- объяснить разницу между
CMDиENTRYPOINTи корректно комбинировать их; - объяснить разницу между
ARGиENV, включая область видимости и попадание в образ; - диагностировать инвалидацию build cache и упорядочить инструкции так, чтобы кэш работал;
- применять возможности BuildKit: cache mounts, secret mounts, bind mounts, heredocs;
- писать multi-stage builds и собирать конкретную стадию через
--target; - настраивать
HEALTHCHECKи объяснять, когда он не нужен; - обеспечивать воспроизводимость сборки: pinned versions, digests, lock files.
Предварительные знания
- Раздел 03. Работа с Images — слои и их неизменяемость;
- Раздел 04. Containers и lifecycle — что такое главный процесс и сигналы;
- базовое владение shell: переменные, кавычки, конвейеры.
Материалы
-
Build context и
.dockerignore
Что именно отправляется daemon при сборке и почему это может занимать минуты. Синтаксис.dockerignore, типичный набор исключений для Python-проекта, влияние контекста на build cache и на утечку файлов в образ. -
Базовые инструкции
FROM,ARG,ENV,WORKDIR,LABEL,USER,EXPOSE,VOLUME,SHELL,STOPSIGNAL,ONBUILD. Для каждой: назначение, синтаксис, пример, типичная ошибка и когда применять не следует. Область видимостиARGи его отличие отENV. -
COPY, ADD и RUN
ПочемуCOPYпредпочтительнееADDи в каких двух случаяхADDуместен.COPY --from,--chown,--link,--parents. Объединение команд в одномRUN,--no-install-recommends, очистка в том же слое, heredoc-синтаксис. -
CMD и ENTRYPOINT
Exec form против shell form и последствия для сигналов. Все комбинацииCMDиENTRYPOINTс таблицей результирующей команды. Паттерн entrypoint-скрипта иexec "$@". Переопределение при запуске. -
Build cache
Правила инвалидации кэша для каждой инструкции. Почему изменение кода не должно пересобирать зависимости. Порядок инструкций как инженерное решение. Диагностика: чтение вывода сборки,--progress=plain,--no-cache. -
BuildKit
Что изменилось по сравнению с legacy builder. Директива# syntax=docker/dockerfile:1. Cache mounts для менеджеров пакетов, secret mounts вместо build args для паролей, bind mounts вместо копирования, параллельная сборка стадий.docker buildx buildи build drivers. -
Multi-stage builds
Разделение окружения сборки и окружения выполнения. Именование стадий,COPY --from,--target, общие базовые стадии. Практическое сравнение размеров. Когда multi-stage не нужен. -
HEALTHCHECK
Синтаксис и параметры--interval,--timeout,--start-period,--start-interval,--retries. Как Docker использует статус health. Отличие от readiness. Почему healthcheck в образе не всегда правильное решение и когда лучше описать его в Compose. -
Воспроизводимые сборки
Pinning base image по tag и по digest, фиксация версий пакетов, lock files, влияние времени сборки на результат. Provenance и SBOM: что это и как получить. Ограничения полной воспроизводимости. -
Практические задания
Лабораторные задания раздела с проверкой результата.
Рекомендуемый порядок чтения
Последовательный: 01 → 02 → 03 → 04 → 05 → 06 → 07 → 08 → 09 → exercises.
Уроки 04 и 05 — ключевые: они объясняют две самые частые категории ошибок в реальных Dockerfile. Урок 09 можно отложить до раздела 11. Production, если сейчас важнее скорость.
Практические задания
| № | Задание | Тип |
|---|---|---|
| 1 | Измерить размер build context до и после добавления .dockerignore | обяз. |
| 2 | Собрать образ, намеренно сломать кэш, найти инструкцию-виновника по выводу сборки | обяз. |
| 3 | Переупорядочить инструкции так, чтобы изменение кода не пересобирало зависимости; измерить время до и после | обяз. |
| 4 | Построить таблицу результирующих команд для всех комбинаций CMD и ENTRYPOINT и проверить её экспериментально | обяз. |
| 5 | Преобразовать одностадийную сборку в multi-stage и сравнить размеры | обяз. |
| 6 | Использовать cache mount для менеджера пакетов и измерить эффект на повторной сборке | доп. |
| 7 | Передать токен через secret mount и доказать через docker history, что он не попал в образ | доп. |
| 8 | Добавить HEALTHCHECK и увидеть переход состояния из starting в healthy | доп. |
| 9 | Дан Dockerfile, где каждая сборка занимает 4 минуты. Найти три причины и исправить | диаг. |
| 10 | Собрать образ, воспроизводимый по digest на двух разных машинах | ★ |
Полные формулировки — в exercises.md.
Критерии завершения раздела
Раздел пройден, когда учащийся может без подсказок:
- Объяснить, что попадёт в образ при
COPY . .и как это ограничить. - Предсказать результирующую команду для любой комбинации
ENTRYPOINTиCMD. - Назвать, что инвалидирует кэш для
COPY,RUNиARG. - Написать multi-stage
Dockerfile, где финальный образ не содержит компилятора и dev-зависимостей. - Объяснить, почему передача пароля через
--build-argнебезопасна, и показать альтернативу. - Объяснить, почему
ENVс секретом хуже, чем secret mount, даже если значение потом перезаписано.
Проверьте себя: Quiz 05.
Что дальше
Раздел дал универсальные правила сборки. Следующий раздел — центральный в курсе — применяет их к Python и добавляет специфику языка: wheels, зависимости, буферизация вывода, worker-процессы.
Навигация
← Предыдущий раздел: Containers и lifecycle
Вернуться к главному оглавлению
Следующий раздел: Python внутри Container →