Влияет ли multi-stage сборка в Docker на безопасность?

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

Ответ

Да, multi-stage сборка — один из ключевых приёмов для создания безопасных Docker-образов, который я применяю в CI/CD пайплайнах.

Основное влияние на безопасность заключается в кардинальном сокращении «поверхности атаки» (attack surface) финального образа.

Без multi-stage (проблемный подход):

FROM golang:1.21  # Полноценный образ с компилятором, git, пакетным менеджером
WORKDIR /app
COPY . .
RUN go build -o myapp
CMD ["./myapp"]

Итоговый образ содержит ВСЕ инструменты сборки (~1 ГБ). Если в пакете golang:1.21 или любой его зависимости обнаружится уязвимость (CVE), она останется в продакшен-образе.

С multi-stage (рекомендуемый подход):

# STAGE 1: Builder — содержит всё для компиляции
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./ 
RUN go mod download  # Кэширование зависимостей
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o myapp .

# STAGE 2: Runner — минимальный финальный образ
FROM alpine:latest  # Или `scratch` для статического бинарника
RUN apk --no-cache add ca-certificates tzdata  # Только необходимые для работы
WORKDIR /root/
COPY --from=builder /app/myapp .
USER nobody:nobody  # Запуск от непривилегированного пользователя
CMD ["./myapp"]

Преимущества для безопасности:

  1. Минимальный финальный образ: В продакшен попадает только статический бинарник myapp и базовые пакеты Alpine (~5-10 МБ вместо 1 ГБ).
  2. Нет инструментов сборки: Нет компилятора (gcc), пакетного менеджера (apt, apk), системы контроля версий (git), которые злоумышленник мог бы использовать при компрометации контейнера.
  3. Меньше пакетов — меньше CVE: Образ Alpine содержит значительно меньше пакетов, чем golang:1.21, что упрощает его сканирование на уязвимости (например, с помощью trivy или docker scout).
  4. Возможность использовать scratch: Для полностью статических бинарников можно использовать пустой образ FROM scratch, что даёт абсолютно минимальную поверхность атаки.

Важный нюанс: Безопасность также зависит от регулярного обновления базового образа (alpine:latest) в финальной стадии для получения исправлений безопасности.