16 KiB
Зачем нужен Dockerfile
Dockerfile - текстовый файл с инструкциями (по одной на строку, логически сверху вниз). Демон Docker читает их и строит образ слоями, почти каждая инструкция добавляет слой.
Сборка:
docker build -t имя:тег -f Dockerfile /путь/к/контексту
Контекст - каталог, из которого разрешено брать файлы для COPY/ADD (часто .). Список исключений — в .dockerignore в корне контекста.
Общие правила файла
- Имя по умолчанию -
Dockerfileв корне контекста; другой файл:docker build -f ./docker/prod.Dockerfile . - Комментарии - строка, начинающаяся с
#. - Продолжение строки - обратный слэш
\в конце строки. - Регистр - инструкции принято писать ЗАГЛАВНЫМИ (
FROM,RUN…), Docker это не требует, просто читается легче. - Первый этап должен начинаться с
FROM(кроме редких случаев сARGдо первогоFROM).
Parser directives (только в самом верху файла)
Их максимум две, только до любых комментариев и инструкций (после пустых строк тоже нельзя вставлять мусор сверху).
# syntax=docker/dockerfile:1 - Включить современный фронтенд Dockerfile (BuildKit, расширенный синтаксис RUN --mount=...).
Сводная таблица инструкций
| Инструкция | Назначение (кратко) |
|---|---|
FROM |
Базовый образ (начало этапа / stage). |
RUN |
Выполнить команду при сборке (новый слой). |
CMD |
По умолчанию команда/аргументы при запуске контейнера (переопределяется docker run ...). |
ENTRYPOINT |
«Точка входа» при запуске; с CMD задаёт аргументы по умолчанию. |
COPY |
Копирование из контекста (или из другого stage) в образ. |
ADD |
Как COPY + tar и URL (реже нужен). |
WORKDIR |
Текущий каталог для последующих инструкций. |
ENV |
Переменные окружения в образе (и при сборке для следующих строк). |
ARG |
Переменные только на время сборки (docker build --build-arg). |
EXPOSE |
Документация портов (не публикует на хост само по себе). |
VOLUME |
Объявить точку монтирования тома по умолчанию. |
USER |
Пользователь для следующих RUN и для процесса при запуске. |
LABEL |
Метаданные ключ=значение. |
STOPSIGNAL |
Какой сигнал послать при docker stop. |
HEALTHCHECK |
Как проверять живость контейнера. |
SHELL |
Какая оболочка для shell-формы RUN/CMD/ENTRYPOINT. |
ONBUILD |
Зарегистрировать инструкцию «выполнить позже», когда от этого образа соберут дочерний (редко). |
Ниже - что писать, какие есть параметры и на что обратить внимание.
FROM - базовый образ
Синтаксис:
FROM [--platform=linux/amd64] image[:tag|@digest] [AS name]
| Элемент | Смысл |
|---|---|
image:tag |
Репозиторий и тег (nginx:1.27-alpine). Лучше фиксировать тег или digest. |
AS name |
Имя этапа для multi-stage и для COPY --from=name. |
--platform=... |
Целевая платформа образа (multi-arch / кросс-сборка). |
Каждый новый FROM начинает новый этап; предыдущие слои остаются в цепочке сборки, в финальный образ попадает только последний этап (если не копировать из предыдущих через COPY --from).
RUN - команды на этапе сборки
Две формы записи:
Shell-форма (через /bin/sh -c в Linux, если не переопределён SHELL):
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
Exec-форма (без оболочки, нет подстановок $VAR шелла, если не передать через оболочку явно):
RUN ["apt-get", "update"]
Часто объединяют команды в одну строку &&, чтобы меньше слоёв и не оставлять кэш пакетов в отдельном слое.
BuildKit: кэш зависимостей, секреты, примонтировать каталог хоста только на время RUN:
# syntax=docker/dockerfile:1
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
Типы type= включают cache, bind, secret, ssh и др. документация BuildKit mounts.
WORKDIR - рабочий каталог
WORKDIR /app
Создаёт каталог, если его нет. Влияет на последующие RUN, COPY, CMD, ENTRYPOINT в exec-форме относительно пути (часть команд всё равно лучше указывать абсолютно).
Можно несколько раз - каждый раз новый путь.
COPY - файлы в образ
COPY [--chown=user:group] [--chmod=755] <src> ... <dest>
COPY ["--chown=user:group", "src с пробелом", "/dest/"]
| Параметр | Смысл |
|---|---|
src |
Путь относительно контекста сборки (не выше контекста). |
dest |
Файл или каталог в образе (обычно абсолютный путь). |
--chown |
Владелец скопированных файлов (uid:gid или имя). |
--chmod |
Права на файлы (новые версии BuildKit). |
--from=stage|index |
Копировать не из контекста, а из другого этапа или именованного образа (COPY --from=nginx:alpine /etc/nginx/nginx.conf /tmp/). |
Несколько src - последний аргумент должен быть каталогом с / на конце.
ADD - расширенное копирование
ADD [--chown=user:group] [--chmod=755] <src> ... <dest>
Поведение как у COPY, плюс:
- локальный
srcв виде tar - может распаковаться вdest. srcкак URL — скачать файл.
Для обычных файлов предпочитают COPY.
ENV - переменные окружения
ENV KEY=value
ENV KEY=value OTHER=val2
ENV KEY="значение с пробелами"
- Доступны в последующих инструкциях Dockerfile и в запущенном контейнере.
- Одна форма
ENV A=B C=Dзадаёт несколько переменных. - Значения можно подставлять в строках как
$KEYили${KEY}.
ARG - переменные только при сборке
ARG VERSION=1.0
ARG GIT_COMMIT
- Значение снаружи:
docker build --build-arg GIT_COMMIT=$(git rev-parse HEAD). ARGдо первогоFROMможет участвовать только в самомFROM(версия базового образа).- После
FROMпеременныеARGнужно объявить снова, если они нужны в этом этапе. - Не храните секреты в
ARGбез BuildKit secrets: значения могут попасть в историю слоёв (docker history).
EXPOSE - какие порты «слушает» приложение
EXPOSE 80
EXPOSE 80/tcp 443/tcp
EXPOSE 53/udp
Это метаданные и подсказка для docker run -P. Порт на хост не открывается, пока не укажете -p или Compose ports:.
VOLUME - каталог для данных вне слоя записи
VOLUME ["/data"]
VOLUME /var/log/app
Объявляет точку, куда при запуске без явного -v Docker может подставить анонимный том. Часто для данных БД или логов. Не путать с явным монтированием в docker run -v.
USER - под каким UID/GID работать
USER nginx
USER 1000:1000
Все последующие RUN и процесс по умолчанию при старте — от этого пользователя (если не переопределить в docker run -u).
LABEL - метаданные образа
LABEL maintainer="you@example.com"
LABEL version="1.0" description="My app"
Пары ключ–значение; удобно для OCI-аннотаций (org.opencontainers.image.*), реестров, политик.
CMD - что выполнять при запуске по умолчанию
Три формы:
CMD ["executable", "param1", "param2"]
CMD ["param1", "param2"]
CMD command param1 param2
| Форма | Смысл |
|---|---|
Exec ["exe", "a"] |
Прямой запуск, PID 1 = exe, сигналы доходят нормально. |
| Exec как аргументы к ENTRYPOINT | Если задан ENTRYPOINT, CMD даёт только аргументы по умолчанию. |
Shell CMD a && b |
Через sh -c; PID 1 = shell - для сигналов и таймаутов остановки хуже, чем exec-форма. |
Переопределение: docker run image ls заменит CMD на ls (если не трогать ENTRYPOINT).
В файле допустима одна инструкция CMD (если несколько, то последняя выполняется).
ENTRYPOINT - фиксированная «обёртка» запуска
ENTRYPOINT ["docker-entrypoint.sh"]
ENTRYPOINT exec java -jar app.jar
- Exec-форма — как с
CMD, хорошо для PID 1. - Shell-форма — через
sh -c.
Частый паттерн: ENTRYPOINT = скрипт или бинарник, CMD = аргументы по умолчанию. Тогда docker run myimage --help передаёт --help в entrypoint.
STOPSIGNAL - сигнал остановки
STOPSIGNAL SIGTERM
Какой сигнал послать процессу при docker stop (по умолчанию обычно SIGTERM, потом SIGKILL). Нужен редко (например, для JVM или nginx с graceful shutdown).
HEALTHCHECK - проверка «жив ли» контейнер
HEALTHCHECK [OPTIONS] CMD command
OPTIONS:
| Опция | Смысл |
|---|---|
--interval=DURATION |
Как часто (по умолчанию 30s). |
--timeout=DURATION |
Таймаут одной проверки (default 30s). |
--start-period=DURATION |
«Прогрев»: неудачи не считаются failure (default 0s). |
--retries=N |
Сколько подряд неуспехов → unhealthy (default 3). |
CMD здесь - команда проверки (часто curl/wget к localhost или скрипт).
HEALTHCHECK NONE - отключить наследованный healthcheck от базового образа.
SHELL - оболочка для shell-форм
SHELL ["powershell", "-command"]
SHELL ["/bin/bash", "-c"]
Меняет команду для shell-формы RUN, CMD, ENTRYPOINT на Windows/Linux.
ONBUILD - отложенная инструкция для «дочерних» образов
ONBUILD COPY . /app/src
Выполнится не при сборке этого образа, а когда другой Dockerfile сделает FROM этого образа. Сейчас редко используют (Compose/build args проще отследить).
Многоэтапная сборка (FROM ... AS + COPY --from)
Несколько блоков FROM ... AS builder / FROM ... AS production. Из «тяжёлого» этапа в «лёгкий» переносят только артефакты:
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
Имена этапов - в AS; копирование - COPY --from=build или --from=0 (индекс этапа).
COPY vs ADD — что выбрать
| Задача | Инструкция |
|---|---|
| Файлы/папки из контекста в образ | COPY |
Распаковать локальный .tar в слой |
ADD (или COPY + RUN tar) |
| Скачать по URL | лучше RUN curl/wget с проверкой checksum; ADD URL — редко |
.dockerignore
В корне контекста — шаблоны путей, которые не отправляются демону при сборке и недоступны для COPY/ADD:
.git
node_modules
.env
*.md
Сборка и просмотр слоёв
docker build -t my-web:1.0 -f Dockerfile .
docker history my-web:1.0
Готовый пример в репозитории
Рабочие Dockerfile с COPY, EXPOSE, HEALTHCHECK и т.д. — в docker/examples/multi-service/ (web, api, proxy). Связка с Compose — в части 4.
Документация
Полный список инструкций, edge cases и актуальные флаги Dockerfile reference.