Dockerfile: справочник инструкций и значений

Что означает каждая инструкция, какие у неё значения и флаги, и как писать Dockerfile правильно

Общие правила

Инструкции

ИнструкцияНазначениеПример
FROMБазовый образ, с которого начинается сборка. Обязательна первой (кроме ARG перед ней).FROM python:3.12-slim AS build
RUNВыполняет команду во время сборки и фиксирует результат в слое.RUN apt-get update && apt-get install -y curl
CMDКоманда по умолчанию при запуске контейнера. Переопределяется аргументами docker run. В файле допускается одна.CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINTОсновная команда контейнера. Аргументы из docker run добавляются к ней, а не заменяют.ENTRYPOINT ["python", "app.py"]
COPYКопирует файлы из контекста сборки в образ.COPY requirements.txt /app/
ADDКак COPY, но умеет брать URL и распаковывать tar-архивы. Для обычного копирования используйте COPY.ADD archive.tar.gz /opt/
WORKDIRРабочая папка для последующих RUN, CMD, COPY. Создаётся, если её нет.WORKDIR /app
ENVПеременная окружения, сохраняется в образе и в контейнере.ENV APP_ENV=production
ARGПеременная только на этапе сборки. Можно передать через --build-arg. Видна в docker history, поэтому секреты через ARG не передавайте.ARG VERSION=1.0
EXPOSEДокументирует порт, который слушает приложение. Сам по себе порт не публикует, для этого нужен -p.EXPOSE 8080
USERПользователь, от имени которого выполняются RUN, CMD и ENTRYPOINT.USER 10001:10001
VOLUMEОбъявляет точку монтирования для данных. Том создаётся при запуске контейнера.VOLUME ["/var/lib/data"]
LABELМетаданные в виде ключ-значение.LABEL maintainer="ops@example.com" version="1.0"
HEALTHCHECKКоманда проверки здоровья контейнера. Значение NONE отключает проверку из базового образа.HEALTHCHECK CMD curl -f http://localhost:8080/health || exit 1
SHELLМеняет оболочку для RUN, CMD и ENTRYPOINT в shell-форме.SHELL ["/bin/bash", "-c"]
STOPSIGNALСигнал, которым останавливается контейнер (по умолчанию SIGTERM).STOPSIGNAL SIGQUIT
ONBUILDИнструкция, которая выполнится, когда этот образ используют как базовый в другом Dockerfile.ONBUILD COPY . /src
MAINTAINERУстарела. Используйте LABEL maintainer=....—

Формы записи: exec и shell

У CMD, ENTRYPOINT и RUN есть два способа записи, и разница важна.

Флаги инструкций

ФлагГде используетсяЧто делает
--platform=linux/amd64FROMВыбор архитектуры базового образа, например для сборки под ARM.
--from=buildCOPYКопирует файлы из другого этапа сборки, а не из контекста.
--chown=app:appCOPY, ADDЗадаёт владельца скопированных файлов.
--chmod=755COPY, ADDЗадаёт права скопированных файлов.
--interval=30sHEALTHCHECKКак часто выполнять проверку (по умолчанию 30s).
--timeout=3sHEALTHCHECKСколько ждать ответа проверки (по умолчанию 30s).
--start-period=10sHEALTHCHECKПериод прогрева: ошибки в это время не засчитываются (по умолчанию 0s).
--retries=3HEALTHCHECKСколько неудач подряд считаются нездоровьем (по умолчанию 3).
--mount=type=cache,target=/root/.cache/pipRUNКеш между сборками, который не попадает в слой образа.
--network=noneRUNЗапуск команды без сети, например для проверки.

Значения для HEALTHCHECK

Проверка выполняет команду, и её код возврата решает судьбу контейнера: 0 означает «здоров», 1 — «нездоров». Статусы видны в docker ps как healthy, unhealthy или starting.

HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1

Если базовый образ не содержит curl, используйте wget или проверку через свой код.

Многоэтапная сборка

Сборка в несколько этапов позволяет компилировать код с инструментами, а в итоговый образ копировать только результат. Образ становится меньше и безопаснее, потому что компиляторов в нём нет.

FROM golang:1.23 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app ./cmd/app

FROM gcr.io/distroless/static-debian12
COPY --from=build /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]

Пример хорошего Dockerfile для Python

FROM python:3.12-slim

WORKDIR /app

# Сначала зависимости: этот слой кешируется, пока не меняется requirements.txt
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Код меняется часто, поэтому копируем его после зависимостей
COPY . .

RUN useradd --uid 10001 appuser
USER 10001

EXPOSE 8000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

.dockerignore

Файл .dockerignore в корне контекста исключает ненужные файлы из сборки. Это ускоряет сборку и не даёт попасть в образ секретам и служебным папкам.

.git
node_modules
*.log
.env
__pycache__
Не кладите секреты в ENV, ARG или прямо в файлы, которые копируются в образ. Они сохраняются в слоях, и их видно через docker history и docker inspect. Для секретов используйте монтирование при сборке (RUN --mount=type=secret) или переменные среды при запуске.
Запускайте приложение не от root (инструкция USER), используйте конкретные теги базовых образов и держите итоговый образ минимальным. Проверить, что получилось, поможет docker history myapp, который покажет размер каждого слоя.