714просмотров
26.3%от подписчиков
20 марта 2026 г.
Score: 785
🐳 Идеальный Dockerfile для Go. Худеем с 800 МБ до 10 МБ Знакомая картина: джун приносит микросервис, который делает пару запросов к БД, а Docker-образ весит под гигабайт. Почему? Потому что в FROM гордо красуется golang:latest. Вместе с вашим кодом в продакшен уезжает весь тулчейн компилятора, операционная система, куча утилит (шелл, curl) и, как бонус, пачка потенциальных уязвимостей. Прелесть Go в том, что он компилирует всё в один независимый бинарный файл. Нам не нужен Go в рантайме! Наш путь - Multi-stage builds (Многоэтапная сборка). Вот "золотой стандарт" Dockerfile, который работает в 99% случаев: # === Этап 1: Сборка (Builder) ===
FROM golang:1.22-alpine AS builder WORKDIR /app # Шаг 1: Кэшируем зависимости
# Этот слой пересоберется ТОЛЬКО если изменились go.mod или go.sum
COPY go.mod go.sum ./
RUN go mod download # Шаг 2: Копируем код
COPY . . # Шаг 3: Собираем бинарник
# CGO_ENABLED=0 - критически важно для статической линковки
# -ldflags="-w -s" - вырезаем отладочную информацию
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /app/bin/service ./cmd/server/main.go # === Этап 2: Финальный образ (Runner) ===
# Используем distroless вместо alpine или scratch
FROM gcr.io/distroless/static-debian12:nonroot WORKDIR /app # Забираем только готовый бинарник из первого этапа
COPY --from=builder /app/bin/service . # Контейнер будет работать от непривилегированного пользователя
USER nonroot:nonroot EXPOSE 8080
ENTRYPOINT ["/app/service"] Разбираем нюансы под капотом (Senior Edition): • Зачем нужен CGO_ENABLED=0? По умолчанию Go может динамически линковаться с системными C-библиотеками (например, libc). Если вы соберете такой бинарник и положите в пустой образ, он упадет при старте. Отключая CGO, мы принудительно делаем статическую линковку - всё необходимое запекается прямо внутрь файла. • Флаги -ldflags="-w -s": Они вырезают DWARF-таблицы и символы отладки. Это бесплатно срезает ~20-30% веса бинарника. Не переживайте, трейсы паник (stack traces) всё ещё будут показывать номера строк, так что для прода это безопасно. • Почему distroless/static, а не scratch или alpine? * В scratch (абсолютно пустом образе) нет корневых сертификатов (ca-certificates). Как только ваш сервис попытается сделать внешний HTTPS-запрос, он упадет. Там также нет таймзон (tzdata). - В alpine есть sh (шелл) и пакетный менеджер apk - это векторы атаки для хакеров, если они найдут RCE в вашем коде. - Google Distroless содержит только сертификаты, таймзоны и юзера nonroot. Идеальный баланс микроскопического размера (~2 МБ) и безопасности. У кого образы до сих пор весят больше 50 МБ - срочно переписывать! #golang #docker #devops #architecture #security 👉 @golang_lib