Dockerfile cheat sheet
Инструкции с синтаксисом, возможности BuildKit и шаблоны для Python.
Строка
# syntax=docker/dockerfile:1в начале файла обязательна для--mount,--secretи heredoc. Без неё эти конструкции не распознаются, и сборка падает с невнятной ошибкой.
Содержание
Инструкции
| Инструкция | Синтаксис | Заметка |
|---|---|---|
FROM | FROM образ:тег AS имя | Для воспроизводимости — по digest |
ARG | ARG ИМЯ=умолчание | До FROM виден только в FROM |
ENV | ENV KEY=value | Попадает в образ и в inspect |
WORKDIR | WORKDIR /app | Создаёт каталог, если его нет |
COPY | COPY источник цель | Предпочтителен перед ADD |
COPY --from | COPY --from=стадия /путь /путь | Из другой стадии или образа |
COPY --chown | COPY --chown=10001:10001 . . | Без отдельного RUN chown |
ADD | ADD архив.tar /путь | Распаковывает и качает по URL — неявно |
RUN | RUN команда | Каждая — отдельный слой |
CMD | CMD ["a", "b"] | Заменяется аргументами docker run |
ENTRYPOINT | ENTRYPOINT ["a"] | Аргументы docker run добавляются |
USER | USER 10001:10001 | Числом, а не именем |
EXPOSE | EXPOSE 8000 | Только документация; ничего не публикует |
VOLUME | VOLUME ["/data"] | Создаёт анонимный том, если не задан явный |
HEALTHCHECK | HEALTHCHECK CMD ... | Выполняется внутри container'а |
LABEL | LABEL ключ="значение" | Метаданные для прослеживаемости |
SHELL | SHELL ["/bin/bash", "-c"] | Меняет оболочку для shell-формы |
STOPSIGNAL | STOPSIGNAL SIGTERM | Сигнал, посылаемый при docker stop |
ONBUILD | ONBUILD COPY . /app | Срабатывает у потомка; источник сюрпризов |
Формы записи
CMD ["python", "-m", "app"] # exec-форма: PID 1 — сам процесс
CMD python -m app # shell-форма: PID 1 — /bin/sh
Последствия shell-формы:
| Что | Результат |
|---|---|
SIGTERM при docker stop | Приходит оболочке; она не пересылает |
Аргументы docker run | Теряются |
| Время остановки | Ровно grace period, затем SIGKILL |
Правило: exec-форма всегда, кроме случаев, где нужна подстановка оболочки — и тогда явно CMD ["sh", "-c", "..."].
ENTRYPOINT и CMD вместе
ENTRYPOINT ["python", "-m", "app"]
CMD ["--help"]
| Команда | Что выполнится |
|---|---|
docker run образ | python -m app --help |
docker run образ --top 3 | python -m app --top 3 |
docker run --entrypoint sh образ | sh |
Возможности BuildKit
Cache mount
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
Кэш живёт вне слоёв. Не сочетать с --no-cache-dir — он отключает ровно то, что кэшируется.
Не переносится в CI: cache-to экспортирует слои, а не содержимое cache mount (урок 16.3).
Secret mount
RUN --mount=type=secret,id=токен \
TOKEN="$(cat /run/secrets/токен)" ./скрипт.sh
docker build --secret id=токен,src=./токен.txt .
Секрет доступен во время инструкции и в слой не пишется. Единственный правильный способ (урок 12.6).
Bind mount
RUN --mount=type=bind,source=.,target=/src \
cp /src/файл /app/
Файлы доступны без копирования в слой.
Heredoc
COPY <<'EOF' /app/entrypoint.sh
#!/bin/sh
exec python -m app "$@"
EOF
RUN <<'EOF'
apt-get update
apt-get install -y --no-install-recommends curl
rm -rf /var/lib/apt/lists/*
EOF
Требует строки # syntax.
Экспорт кэша в registry
docker buildx build \
--cache-from type=registry,ref=имя:buildcache \
--cache-to type=registry,ref=имя:buildcache,mode=max \
--tag имя:тег --load .
mode=max обязателен. Умолчание min экспортирует только последнюю стадию, и слой с зависимостями в кэш не попадает.
Multi-stage
# syntax=docker/dockerfile:1
FROM python:3.13-slim AS base
ENV PYTHONUNBUFFERED=1 PATH=/opt/venv/bin:$PATH
WORKDIR /app
FROM base AS deps
RUN python -m venv /opt/venv
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
FROM deps AS test
COPY requirements-dev.txt .
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements-dev.txt
COPY . .
RUN python -m pytest -q --cov=app --cov-fail-under=85
FROM base AS runtime
COPY --from=deps /opt/venv /opt/venv
COPY app/ ./app/
USER 10001:10001
ENTRYPOINT ["python", "-m", "app"]
| Команда | Что соберётся |
|---|---|
docker build . | Только base, deps, runtime |
docker build --target test . | base, deps, test |
Стадия test при обычной сборке не выполняется. Она никому не нужна для runtime, и сборка проходит успешно даже со сломанными тестами. Запускать явно (урок 15.5).
Виртуальное окружение по фиксированному пути копируется одной инструкцией и не зависит от версии Python в путях.
Шаблоны для Python
Минимальный сервис
# syntax=docker/dockerfile:1
FROM python:3.13-slim
ENV PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt
COPY app/ ./app/
USER 10001:10001
EXPOSE 8000
ENTRYPOINT ["python", "-m", "app"]
Healthcheck без curl
HEALTHCHECK --interval=10s --timeout=3s --start-period=15s --retries=3 \
CMD ["python", "-c", "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/healthz').status==200 else 1)"]
curl в slim и alpine отсутствует; проверка вернёт код 127.
--start-period должен превышать время старта приложения, иначе проверки во время инициализации пометят container нездоровым.
Каталог для записи при read_only
RUN mkdir -p /var/lib/app && chown 10001:10001 /var/lib/app
USER 10001:10001
Каталог создаётся в образе с нужным владельцем — иначе пустой том достанется root.
Установка системных пакетов
RUN apt-get update \
&& apt-get install -y --no-install-recommends пакет \
&& rm -rf /var/lib/apt/lists/*
Три условия сразу: update и install в одной инструкции (иначе кэшированный индекс устареет), --no-install-recommends, удаление кэша в той же RUN.
Метки прослеживаемости
ARG VCS_REF=unknown
LABEL org.opencontainers.image.revision="$VCS_REF" \
org.opencontainers.image.source="https://github.com/org/repo"
Правила порядка
1. # syntax
2. FROM (базовый образ, по возможности по digest)
3. ENV, ARG — редко меняются
4. Системные пакеты — меняются редко
5. Файл зависимостей + установка ← до исходников!
6. Исходный код ← меняется чаще всего
7. USER
8. EXPOSE, HEALTHCHECK
9. ENTRYPOINT, CMD
Пятый и шестой пункты определяют, работает ли кэш. COPY . . до установки зависимостей — самая частая причина «сборка стала медленной».
Что проверить перед тем, как считать Dockerfile готовым
| Проверка | Команда |
|---|---|
| Кэш работает | touch src/*.py && time docker build . — секунды |
Пользователь не root и числовой | docker image inspect образ --format '{{.Config.User}}' |
| Точка входа в exec-форме | docker image inspect образ --format '{{json .Config.Entrypoint}}' |
| Мягкая остановка | docker run -d --name t образ && time docker stop t |
| Секретов в истории нет | docker history --no-trunc образ | grep -iE 'password|secret' |
| Работает только для чтения | docker run --rm --read-only --tmpfs /tmp образ |
| Тесты останавливают сборку | Сломать тест, docker build --target test . |
Подробнее: раздел 05, Python container checklist.
Навигация
Вернуться к справочникам
Docker CLI cheat sheet
Compose cheat sheet
Python container checklist
Главное оглавление