Какую проблему решают многоэтапные сборки (multi-stage builds) в Docker

Ответ

Многоэтапные сборки (multi-stage builds) в Docker решают проблему избыточного размера и сниженной безопасности финальных образов.

Это достигается за счет разделения Dockerfile на несколько этапов (блоков FROM). Один или несколько начальных этапов используются для компиляции, сборки и установки зависимостей, а финальный этап копирует только необходимые артефакты (например, скомпилированный бинарный файл или production-зависимости) из предыдущих этапов.

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

# --- Этап 1: Сборка (Builder) ---
# Используем полный образ Go со всеми инструментами для сборки
FROM golang:1.19 as builder

WORKDIR /app
COPY . .

# Собираем приложение. Флаги убирают отладочную информацию и статически линкуют
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# --- Этап 2: Финальный образ (Final) ---
# Используем минималистичный образ без исходников и инструментов
FROM alpine:latest

WORKDIR /root/

# Копируем только скомпилированный бинарный файл из этапа 'builder'
COPY --from=builder /app/main .

# Команда для запуска приложения
CMD ["./main"]

Ключевые преимущества:

  • Минимальный размер образа: В финальный образ не попадают компиляторы, dev-зависимости, исходный код и временные файлы. Образ golang:1.19 весит ~1 ГБ, а alpine — всего ~5 МБ.
  • Повышенная безопасность: Меньше компонентов в образе означает меньшую поверхность для атак.
  • Упрощение CI/CD: Весь процесс сборки описывается в одном Dockerfile, не требуя внешних скриптов для очистки.