Напишите multi-stage Dockerfile, дающий минимальный финальный образ для Go-приложения.
Соберите Go-веб-сервис в минимальный production-образ. Сборке нужен тулчейн Go, но финальный образ должен нести только скомпилированный бинарник — без компилятора, без исходников, без пакетного менеджера.
Ограничения:
- Две стадии: сборщик на Go SDK и крошечная стадия рантайма.
- Скопировать модульные файлы и
go mod downloadдо копирования кода, ради кэша. - Финальная стадия НЕ должна содержать тулчейн Go.
- Запуск от непривилегированного пользователя.
# Заполните multi-stage-сборку.
FROM golang:1.22
# ... стадия сборки ...
# ... минимальная финальная стадия ...
Напишите полный multi-stage Dockerfile.
Сборщик на golang:1.22 копирует go.mod/go.sum, делает go mod download, затем собирает статический бинарник. Финальная стадия — FROM gcr.io/distroless/static и делает COPY --from=builder только бинарника, от non-root. Образ без компилятора и кода, поэтому весит единицы мегабайт.
- ✗Удалять тулчейн в позднем слое вместо отдельной финальной стадии
- ✗Копировать код до go.mod/go.sum — кэш загрузки модулей ломается при правках
- ✗Думать, что Go-бинарнику нужен тулчейн в рантайме для исполнения
- →Почему статически слинкованный Go-бинарник работает на
scratch/distroless без libc? - →Чем отличалась бы аналогичная multi-stage-сборка Node, раз у неё нет статического бинарника?
Две стадии: жирный сборщик на Go SDK и крошечный рантайм. Модульные файлы копируем и качаем до кода, чтобы правки не ломали кэш go mod download. Финальная стадия distroless/static несёт только бинарник — без компилятора, без исходников, работает от non-root.
FROM golang:1.22 AS builder
WORKDIR /src
# Модули — до кода: этот слой переживает правки исходников.
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# Статический бинарник без внешних зависимостей.
RUN CGO_ENABLED=0 go build -o /app ./cmd/server
FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app /app
USER nonroot
ENTRYPOINT ["/app"]