Что такое Multi-stage builds в Docker?

«Что такое Multi-stage builds в Docker?» — вопрос из категории Docker, который задают на 35% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Multi-stage builds — это функция Docker, позволяющая использовать несколько инструкций FROM в одном Dockerfile. Каждая стадия начинается с нового базового образа и может копировать артефакты из предыдущих стадий. Главная цель — создать минимальный итоговый образ, не содержащий инструментов сборки и промежуточных файлов.

Проблема, которую это решает: Традиционный Dockerfile для компилируемого языка (Go, C++) включает в финальный образ компилятор, исходный код и все зависимости для сборки, что сильно увеличивает размер и поверхность для атак.

Пример для Go-приложения:

# --- СТАДИЯ 1: Сборка (builder) ---
# Используем полный образ с Go и компилятором
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./ 
RUN go mod download
COPY . .
# Компилируем статичный бинарник
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# --- СТАДИЯ 2: Запуск (final) ---
# Используем пустой минимальный образ
FROM scratch
WORKDIR /root/
# Копируем ТОЛЬКО скомпилированный бинарник из стадии 'builder'
COPY --from=builder /app/main .
# Копируем SSL-сертификаты (необходимы для многих сетевых вызовов)
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Запускаем приложение
CMD ["./main"]

Преимущества:

  • Размер: Итоговый образ уменьшается с ~350 МБ (полный Go-образ) до ~10 МБ (один бинарник).
  • Безопасность: В финальном образе нет компилятора, shell или пакетного менеджера, что сокращает векторы атак.
  • Чистота: В образе только то, что нужно для запуска приложения.