Ответ
Многоэтапные сборки (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, не требуя внешних скриптов для очистки.