← Назад к вопросам

За счет чего достигается Multi-stage

2.0 Middle🔥 211 комментариев
#Docker и контейнеризация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

За счет чего достигается Multi-stage в Docker

Multi-stage (многостадийная сборка) в Docker — это методика создания оптимизированных Docker-образов за счет использования нескольких этапов (стадий) сборки внутри одного Dockerfile. Ключевая идея заключается в разделении среды сборки (build environment) и финальной среды выполнения (runtime environment), что позволяет исключить из итогового образа ненужные инструменты, зависимости и артефакты промежуточной сборки.

Основные механизмы достижения Multi-stage

  1. Несколько инструкций FROM в одном Dockerfile
    Каждая инструкция FROM начинает новую стадию сборки. Вы можете дать стадиям имена (алиасы) с помощью ключевого слова AS, чтобы ссылаться на них в последующих инструкциях.

    # Стадия сборки (builder stage)
    FROM golang:1.21-alpine AS builder
    WORKDIR /app
    COPY . .
    RUN go build -o myapp .
    
    # Финальная стадия (runtime stage)
    FROM alpine:latest
    WORKDIR /root/
    COPY --from=builder /app/myapp .
    CMD ["./myapp"]
    
  2. Избирательное копирование артефактов между стадиями
    Инструкция COPY --from=<stage_name> позволяет копировать только необходимые файлы из предыдущих стадий. Это основной инструмент для "очистки" финального образа.

    COPY --from=builder /app/compiled-binary /usr/local/bin/
    
  3. Использование разных базовых образов для разных стадий

    • Для стадии сборки: Используются "тяжелые" образы с полным набором инструментов (компиляторы, библиотеки разработки, пакетные менеджеры).
     Примеры: `golang:latest`, `node:18`, `python:3.11-slim` с установленными build-зависимостями.
  • Для финальной стадии: Используются минималистичные образы, содержащие только необходимые для запуска приложения компоненты.
     Примеры: `alpine:latest` (всего 5 МБ), `distroless` образы от Google, `scratch` (пустой образ).

Конкретные примеры оптимизаций

Для Go-приложений:

# Стадия сборки с полным Go SDK
FROM golang:1.21 AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

# Финальная стадия на основе scratch (минимальный возможный образ)
FROM scratch
COPY --from=builder /src/app /app
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
CMD ["/app"]

Для Node.js приложений:

# Стадия сборки с установкой всех зависимостей и сборкой
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Финальная стадия только с production-зависимостями
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
USER node
CMD ["node", "dist/index.js"]

Для приложений на языках со статической компиляцией (Rust, C++) можно использовать даже образ scratch, что дает минимальный размер:

FROM rust:1.70 AS builder
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release

FROM scratch
COPY --from=builder /usr/src/app/target/release/myapp /
CMD ["/myapp"]

Преимущества Multi-stage сборки

  • Значительное уменьшение размера финального образа
    Пример: Go-приложение, собранное с golang:1.21 (~1 ГБ) и развернутое на alpine:latest (~5 МБ), экономит ~995 МБ.

  • Повышение безопасности

    • В финальном образе отсутствуют компиляторы, отладчики, пакетные менеджеры
    • Меньше surface area для потенциальных атак
    • Можно использовать минималистичные образы без shell (например, distroless)
  • Упрощение зависимостей

    • Четкое разделение development и production зависимостей
    • Исключаются конфликты версий инструментов сборки и среды выполнения
  • Снижение затрат на хранение и передачу образов
    Меньшие образы быстрее загружаются из registry, экономят дисковое пространство и сетевой трафик.

Продвинутые техники Multi-stage

  1. Использование стадий как кэша
    Вы можете повторно использовать стадии для кэширования зависимостей:

    FROM node:18 AS deps
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    
    FROM deps AS builder
    COPY . .
    RUN npm run build
    
  2. Параллельная сборка нескольких артефактов
    В разных стадиях можно собирать разные компоненты системы.

  3. Использование внешних образов как источников

    COPY --from=nginx:alpine /etc/nginx/nginx.conf /etc/nginx/nginx.conf
    

Практические рекомендации

  • Всегда именуйте стадии (AS builder) для удобства сопровождения
  • Копируйте только необходимые артефакты — избегайте COPY --from=builder /app ./
  • Для скриптовых языков (Python, PHP) используйте отдельную стадию для установки зависимостей компиляции
  • Тестируйте финальный образ на наличие уязвимостей с помощью docker scout или trivy

Multi-stage сборка стала стандартом де-факто для production-образов, сокращая размеры образов в 5-10 раз и значительно повышая безопасность контейнеризированных приложений. Это обязательный навык для современного DevOps-инженера, непосредственно влияющий на эффективность CI/CD пайплайнов и инфраструктуры контейнеров.

За счет чего достигается Multi-stage | PrepBro