Files
docker/docs/3. Dockerfile - сборка образа и COPY.md
2026-05-04 12:07:58 +03:00

16 KiB
Raw Permalink Blame History

Зачем нужен Dockerfile

Dockerfile - текстовый файл с инструкциями (по одной на строку, логически сверху вниз). Демон Docker читает их и строит образ слоями, почти каждая инструкция добавляет слой.

Сборка:

docker build -t имя:тег -f Dockerfile /путь/к/контексту

Контекст - каталог, из которого разрешено брать файлы для COPY/ADD (часто .). Список исключений — в .dockerignore в корне контекста.

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

  1. Имя по умолчанию - Dockerfile в корне контекста; другой файл: docker build -f ./docker/prod.Dockerfile .
  2. Комментарии - строка, начинающаяся с #.
  3. Продолжение строки - обратный слэш \ в конце строки.
  4. Регистр - инструкции принято писать ЗАГЛАВНЫМИ (FROM, RUN…), Docker это не требует, просто читается легче.
  5. Первый этап должен начинаться с 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.