Логотип Workflow

Article

Updated at:

Dockerfile Deep Dive

Этап 3 - Глубокий разбор Dockerfile

Dockerfile — это не место для случайных Linux-команд. Это рецепт сборки image из чистого context. Хороший Dockerfile объясняет, как создается runtime.

Docker Глубокий разбор Dockerfile

Читайте Dockerfile как рецепт

FROM выбирает base image. RUN выполняет build-time commands. COPY переносит project files в image. WORKDIR задает default directory. EXPOSE документирует ожидаемый port. CMD задает default startup command.

FROM eclipse-temurin:21-jre
WORKDIR /app
COPY app.jar app.jar
EXPOSE 8080
CMD java -jar app.jar

Инструкции, которые новички путают

ADD похож на COPY, но имеет дополнительное поведение: распаковку архивов и работу с remote URL. Новичкам лучше выбирать COPY, пока эти возможности действительно не нужны. В Dockerfile предсказуемость важнее хитрости.

ENTRYPOINT и CMD часто путают. ENTRYPOINT делает container похожим на fixed executable. CMD лучше подходит для default arguments или заменяемой default command. ENV сохраняется в final image и runtime; ARG существует во время build. Ни то, ни другое не должно использоваться для встраивания secrets в image layers.

Build context имеет значение

Когда вы запускаете docker build ., последняя точка — это build context. Docker отправляет эту директорию builder. Dockerfile может копировать files только из этого context, если не использовать advanced features. Поэтому Dockerfile, зависящий от файлов вне project, хрупкий.

Файл .dockerignore — часть хорошего Dockerfile workflow. Он не дает лишним files вроде build outputs, IDE folders, logs и local secrets попасть в build context. Меньший context ускоряет build и снижает риск утечки files в image.

Новички часто смотрят только на видимые Dockerfile instructions. На практике context и ignore rules не менее важны, потому что они определяют, что build вообще может видеть.

Cache-friendly порядок

Порядок Dockerfile instructions влияет на cache. Стабильные files нужно копировать раньше часто меняющихся. Например, Java build может сначала копировать dependency descriptors, resolve dependencies, и только потом копировать source code.

Этот pattern важен, потому что dependencies меняются реже, чем application code. Если изменился только controller, Docker не должен заново выполнять dependency download steps. Хороший Dockerfile делает частые изменения дешевыми.

Та же идея относится к cleanup. Если package manager caches созданы в одном layer, а очищены в другом, ранний layer все равно может нести лишний вес. Install и cleanup часто нужно делать в одной RUN instruction.

Где происходит build

docker build выполняется на Docker host. В beginner setup этот host — ваша машина через Docker Desktop или Docker Engine. В CI Docker host — это CI runner. На production server builds обычно не должны выполняться вручную; server должен скачивать image, который CI уже собрал и опубликовал.

Build context отправляется из project directory в Docker builder. Поэтому commands внутри Dockerfile не видят весь ваш компьютер. Они видят только build context и то, что создали предыдущие Dockerfile instructions.

Dockerfile — это не script, который изменяет ваш ноутбук. Он создает image layers внутри Docker build environment. Если в Dockerfile есть RUN apt-get install ..., packages устанавливаются в image layer, а не в вашу macOS, Windows или host Linux system.

Команды: запустить и проверить

Выполняйте эти commands в terminal той машины, где установлен Docker. Для локального обучения это terminal на вашем ноутбуке. Для VPS сначала подключитесь к server по SSH, затем запускайте commands там. Не вставляйте commands вслепую: запустите одну command, посмотрите, что изменилось, затем переходите к следующей.

docker build -t app:dev .
docker run --rm -p 8080:8080 app:dev
docker history app:dev

Таблица для ориентира

ТемаЧто означаетПрактический вывод
FROMBase image и семейство runtimeИспользуйте trusted explicit versions
RUNBuild-time commandДумайте о cache и cleanup
COPYProject files внутрь imageПредпочитайте COPY для обычного копирования
CMDDefault runtime commandМожет быть переопределена через docker run

Привычка review Dockerfile

Читайте Dockerfile в два прохода. Первый проход: понять историю от base image до startup command. Второй проход: найти build cache problems, unnecessary packages, secrets и files, скопированные слишком рано.

Частая ошибка новичка — Dockerfile, который работает только потому, что на host machine уже что-то установлено. Правильный Dockerfile должен собираться из declared context.

Контрольная точка

Продолжайте, когда можете объяснить, что меняет каждая instruction: filesystem, metadata, build-time variable, runtime environment или startup behavior.

Практика: чтение Dockerfile

Возьмите Dockerfile и подпишите каждую строку одним из четырех labels: base, build, filesystem или runtime. FROM — base. RUN обычно build плюс filesystem. COPY — filesystem. CMD или ENTRYPOINT — runtime. Если строка не подходит ни под один label, обсудите, должна ли она вообще быть в Dockerfile. Такая разметка быстро показывает confusing instructions.