diff --git a/.github/scripts/go-version.sh b/.github/scripts/go-version.sh index 9ce6fab1a..d01bdb913 100755 --- a/.github/scripts/go-version.sh +++ b/.github/scripts/go-version.sh @@ -35,10 +35,10 @@ if [ ! -f "$dockerfile" ]; then exit 1 fi -version=$(sed -nE 's/^FROM[[:space:]]+golang:([0-9]+\.[0-9]+\.[0-9]+)[^[:space:]]*.*/\1/p' "$dockerfile" | sort -u) +version=$(sed -nE 's/^FROM[[:space:]]+(--platform=[^[:space:]]+[[:space:]]+)?golang:([0-9]+\.[0-9]+\.[0-9]+)[^[:space:]]*.*/\2/p' "$dockerfile" | sort -u) if [ -z "$version" ]; then - echo "$dockerfile: no pinned 'FROM golang:X.Y.Z-...' base image found" >&2 + echo "$dockerfile: no pinned 'FROM [--platform=...] golang:X.Y.Z-...' base image found" >&2 exit 1 fi diff --git a/Dockerfile b/Dockerfile index 733fb5e37..01db04889 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,13 @@ # This image is also the single source of truth for the Go toolchain: CI reads the # version out of this line (see .github/scripts/go-version.sh) so tests and images # always run the same runtime. -FROM golang:1.27.3-alpine3.24@sha256:f2c872bcee949b7be9c490efd02b48a8a2fbf947cdf533f1c58525ec9d8170fd AS builder +# --platform=$BUILDPLATFORM pins the BUILDER to the host's own architecture. The +# build below already cross-compiles explicitly (CGO_ENABLED=0, GOOS=linux, +# GOARCH=$TARGETARCH), so the toolchain never needs to be the target's arch — +# and without this line a cross-arch build runs the whole Go compilation under +# QEMU emulation, which is roughly an order of magnitude slower for an identical +# binary. Only the final stage stays on $TARGETPLATFORM, where it belongs. +FROM --platform=$BUILDPLATFORM golang:1.27.3-alpine3.24@sha256:f2c872bcee949b7be9c490efd02b48a8a2fbf947cdf533f1c58525ec9d8170fd AS builder ARG TARGETPLATFORM ARG TARGETARCH