Гайды
Многостадийные Docker-образы (multi-stage)
Несколько FROM, Python и Node примеры, кэш BuildKit, distroless и чек-лист перед релизом.
~8 мин чтения
Многостадийные Docker-образы (multi-stage)
Multi-stage build — несколько директив FROM в одном Dockerfile: на промежуточных стадиях ставят компиляторы и dev-зависимости, в финальный образ копируют только артефакты. Меньше размер, меньше CVE, быстрее pull. База — Docker: контейнеризация.
В начале Dockerfile имеет смысл указать # syntax=docker/dockerfile:1 — включает актуальные фичи BuildKit на стороне билдера.
1. Пример Python
FROM python:3.12-slim AS builder
WORKDIR /build
RUN pip install poetry
COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
RUN pip wheel --no-cache-dir --wheel-dir /wheels -r requirements.txt
FROM python:3.12-slim AS runtime
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
COPY --from=builder /wheels /wheels
RUN pip install --no-cache /wheels/*
COPY . .
USER nobody
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Стадия builder не попадает в финальный образ (кроме явно скопированного).
2. Node (сборка фронта)
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine AS runtime
COPY --from=build /app/dist /usr/share/nginx/html
3. Кэш BuildKit
--mount=type=cache для npm/pip ускоряет CI при включённом BuildKit (DOCKER_BUILDKIT=1).
COPY --link (BuildKit) позволяет параллелить слои и уменьшает инвалидацию кэша при изменении порядка COPY — удобно в больших репозиториях.
Сборка только одной стадии для CI-линта: docker build --target builder . — не тратите время на финальный runtime-слой.
4. SBOM и сканирование
После сборки прогоняте docker scout / Trivy / Grype по финальному образу; multi-stage уменьшает поверхность. Подпись образа (cosign) — для supply chain.
5. Платформы и воспроизводимость
ARG для версий языка и зависимостей; --platform в CI при кросс-сборке (arm64/amd64). Для одинакового результата на разных машинах комбинируйте digest-пин базового образа и зафиксированный lockfile зависимостей.
6. distroless / scratch
Для Go-бинарников финальная стадия gcr.io/distroless/static или scratch + копирование статического ELF — минимальный attack surface.
7. Чек-лист
- Имена стадий (
AS builder) для читаемости. - Не копировать
.gitи тестовые фикстуры в runtime. - Проверять размер и
docker historyперед релизом. -
.dockerignore, чтобы не тащитьnode_modulesи артефакты в контекст. - Пин базовых образов по digest при жёсткой воспроизводимости.
Дальше: Compose · тег Docker