Build stage pinned to BUILDPLATFORM and GOARCH driven by TARGETARCH, so an amd64 image builds natively from an arm64 workstation instead of running the Go toolchain under QEMU. TARGETARCH defaults to amd64 — every cluster node is amd64, and a plain docker build on arm64 would otherwise produce an image the nodes cannot run.
54 lines
2.0 KiB
Docker
54 lines
2.0 KiB
Docker
# Multi-stage build for the API gateway.
|
|
#
|
|
# The runtime stage is distroless/static: no shell, no package manager, no libc.
|
|
# That is deliberate — see tasks/6.1-hardened-image.md. It also means the binary
|
|
# must be fully static, hence CGO_ENABLED=0.
|
|
|
|
# --platform=$BUILDPLATFORM pins the build stage to the machine doing the
|
|
# building, then Go cross-compiles to $TARGETARCH. Without it, building an
|
|
# amd64 image from an arm64 workstation runs the whole toolchain under QEMU.
|
|
FROM --platform=$BUILDPLATFORM golang:1.25-bookworm AS build
|
|
|
|
WORKDIR /src
|
|
|
|
# Copy the module files first so dependency download is cached independently of
|
|
# source changes. The gateway is stdlib + yaml.v3 only, so this is fast either way.
|
|
COPY go.mod go.sum ./
|
|
RUN go mod download
|
|
|
|
COPY . .
|
|
|
|
# VERSION is stamped in so a running pod can be traced back to an exact build.
|
|
ARG VERSION=dev
|
|
|
|
# TARGETARCH is supplied by buildx from --platform. Defaulted to amd64 because
|
|
# every node in the cluster is amd64; a plain `docker build` on an arm64
|
|
# workstation would otherwise silently produce an unrunnable image.
|
|
ARG TARGETARCH=amd64
|
|
|
|
# -trimpath strips local filesystem paths from the binary.
|
|
# -w -s drop DWARF and the symbol table; nothing debugs off the production image.
|
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build \
|
|
-trimpath \
|
|
-ldflags="-w -s -X main.version=${VERSION}" \
|
|
-o /out/gateway ./cmd/gateway
|
|
|
|
# Run the test suite inside the build so a broken commit cannot produce an image.
|
|
# Separate stage: it is skipped unless targeted, keeping the default build fast.
|
|
# CGO_ENABLED=1 here on purpose: the race detector requires cgo, so this cannot
|
|
# reuse the static build's flags.
|
|
FROM build AS test
|
|
RUN go vet ./... && CGO_ENABLED=1 go test ./... -race
|
|
|
|
FROM gcr.io/distroless/static-debian12:nonroot
|
|
|
|
# 65532 is distroless's "nonroot" user. It matches runAsUser in the Deployment's
|
|
# securityContext; if one changes, both must.
|
|
USER 65532:65532
|
|
|
|
COPY --from=build /out/gateway /gateway
|
|
|
|
EXPOSE 8080
|
|
|
|
ENTRYPOINT ["/gateway"]
|