← Назад к вопросам
Где полезна multistage сборка Docker?
2.0 Middle🔥 171 комментариев
#DevOps и инфраструктура
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Многоступенчатая (Multistage) сборка Docker
Multistage сборка — это техника оптимизации Docker образов, позволяющая значительно уменьшить их размер. Она особенно полезна для Python, Go, Java и других языков компиляции.
Проблема без Multistage
Обычный Dockerfile содержит всё в одном образе:
# ❌ Неправильно — всё в одном образе
FROM python:3.11
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Установим build tools для сборки зависимостей
RUN apt-get update && apt-get install -y \
build-essential \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
COPY . .
CMD ["python", "app.py"]
Проблемы:
- Build tools (gcc, make, postgresql-client) остаются в образе
- Кэш pip может быть большим
- Финальный образ весит 800 МБ - 1 ГБ
- Медленная загрузка и развёртывание
Решение: Multistage сборка
Идея: Использовать один образ для сборки, другой для выполнения.
# ✅ Правильно — multistage сборка
# STAGE 1: Builder
FROM python:3.11 as builder
WORKDIR /app
COPY requirements.txt .
# Установим зависимости в виртуальное окружение
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install --no-cache-dir -r requirements.txt
# STAGE 2: Runtime
FROM python:3.11-slim # Меньше base image
WORKDIR /app
# Копируем только виртуальное окружение из builder
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
# Копируем только исходный код (без dev зависимостей)
COPY . .
CMD ["python", "app.py"]
Результат:
- Builder образ (временный, не в финал): 1.2 ГБ
- Runtime образ (финальный): 200-400 МБ ✓
Как работает Multistage
# STAGE 1: builder
FROM golang:1.21 as builder
WORKDIR /app
COPY . .
RUN go build -o app . # Компилируем
# STAGE 2: runtime
FROM scratch # Ультра-минималистичный образ (0 МБ база)
COPY --from=builder /app/app /app
CMD ["/app"]
При сборке:
- Создаётся временный образ
builder - Выполняется вся работа (сборка, установка, компиляция)
- Создаётся финальный образ
- Копируются только нужные артефакты из builder
- Временный образ удаляется
Практические примеры
1. Python приложение с зависимостями
FROM python:3.11 as builder
WORKDIR /tmp
COPY requirements.txt .
# Используем venv для лучшей совместимости
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install --no-cache-dir -r requirements.txt
# Удалим лишнее из venv
RUN find /opt/venv -type d -name __pycache__ -exec rm -rf {} +
RUN find /opt/venv -type f -name "*.pyc" -delete
# Runtime stage
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY . .
EXPOSE 8000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]
2. Node.js приложение
FROM node:20 as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Runtime
FROM node:20-alpine # Меньше база
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
3. Компиляция Go кода
FROM golang:1.21 as builder
WORKDIR /build
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
# Минималистичный runtime
FROM scratch
COPY --from=builder /build/app /app
EXPOSE 8000
CMD ["/app"]
4. Java приложение
FROM maven:3.9 as builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src src
RUN mvn clean package -DskipTests
# Runtime
FROM eclipse-temurin:21-jdk-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
CMD ["java", "-jar", "app.jar"]
Сравнение размеров
# Одноступенчатый Dockerfile для Flask приложения
$ docker build -f Dockerfile.single -t flask:single .
$ docker image ls flask:single
FLASK SINGLE 123abc123 456 MB # ❌ Большой
# Multistage Dockerfile
$ docker build -f Dockerfile.multi -t flask:multi .
$ docker image ls flask:multi
FLASK MULTI 789def789 125 MB # ✅ Меньше на 73%
Оптимизация размера дальше
# Используйте alpine версии (очень маленькие)
FROM python:3.11-alpine as builder
# Очищайте кэш и лишние файлы
RUN pip install --no-cache-dir ...
RUN rm -rf /var/cache/apt/*
# Удаляйте документацию
RUN find /opt/venv -name "*.dist-info" -type d -exec rm -rf {} +
Продвинутые техники
Named stages для сложных проектов
FROM python:3.11 as base
RUN apt-get update && apt-get install -y build-essential
FROM base as builder
RUN pip install -r requirements-dev.txt
FROM base as runtime
RUN pip install -r requirements.txt
COPY --from=builder /opt/venv /opt/venv
FROM runtime as production
# Дополнительная оптимизация для prod
RUN strip /opt/venv/lib/python3.11/*.so
Условная сборка
ARG BUILD_ENV=production
FROM python:3.11 as builder-dev
COPY requirements-dev.txt .
RUN pip install -r requirements-dev.txt
FROM python:3.11 as builder-prod
COPY requirements.txt .
RUN pip install -r requirements.txt
FROM python:3.11-slim as runtime
COPY --from=builder-${BUILD_ENV} /opt/venv /opt/venv
Использование: docker build --build-arg BUILD_ENV=dev .
Когда использовать Multistage
✓ Используйте когда:
- Финальное приложение меньше, чем сборочные артефакты
- Есть build tools, которые не нужны в runtime
- Нужно минимизировать размер образа
- Применяете в микросервисах и Kubernetes
✗ Не нужно если:
- Финальный образ всё равно будет большой
- Используется single-purpose минималистичный образ
Практические советы
- Используйте -slim и -alpine варианты
- Кэшируйте слои правильно — меняющийся код в конце
- Удаляйте временные файлы
- Не копируйте лишнее
- Используйте .dockerignore
Multistage сборка — это стандарт современного Docker контейнеризма и должна использоваться во всех production приложениях.