842просмотров
35.4%от подписчиков
10 марта 2026 г.
question📷 ФотоScore: 926
Знаете ли вы, что multistage build в Docker помогает убрать из образа все лишнее? Собираете приложение в Docker, деплоите в прод, а внутри контейнера лежит весь build toolchain: gcc, make, исходный код, dev-пакеты. Каждый лишний пакет может стать поверхностью для атаки. Multistage build решает эту проблему: собирается в одном образе, а в финальный идет только то, что нужно для запуска. Представим обычный Dockerfile – все в одном образе: FROM golang:1.20-alpine
WORKDIR /app
COPY . .
RUN go build -o myapp
CMD ["./myapp"] Посмотрим что внутри: docker build -t myapp-fat .
docker images myapp-fat
# REPOSITORY TAG SIZE
# myapp-fat latest 350MB 350MB, при том что само приложение весит считанные мегабайты. Остальное – Go SDK, исходники, кеш сборки. Все это едет в продакшен. Multistage build – собираем в одном образе, запускаем из другого: FROM golang:1.20-alpine AS builder
WORKDIR /app
COPY . .
# CGO_ENABLED=0 – статическая линковка, чтобы бинарник работал без libc
RUN CGO_ENABLED=0 go build -o myapp -ldflags="-w -s" FROM alpine:3.18
WORKDIR /app
COPY --from=builder /app/myapp .
USER nobody
CMD ["./myapp"] docker build -t myapp-slim .
docker images myapp-slim
# REPOSITORY TAG SIZE
# myapp-slim latest 12MB Первая стадия – builder – используется только для сборки и в финальный образ не попадает. COPY --from=builder забирает из нее только скомпилированный бинарник. В итоге в проде нет ни SDK, ни исходников, ни dev-зависимостей – только то, что нужно для запуска. Код на салфетке x Кусочки кода