From ad2981541c94623251f5be197da81f215ce104c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ois=C3=ADn=20Kyne?= Date: Wed, 21 Oct 2026 15:26:13 +0000 Subject: [PATCH 1/2] *: cross-compile the docker image instead of emulating arm64 Build the Go binary on the build platform and cross-compile for the target (cgo with gcc-aarch64-linux-gnu for arm64, as the release binaries do), so multi-platform image builds no longer compile under QEMU. Run the version sanity check in the runtime stage, where it now fails the build if the binary can't run. promrated has no cgo deps, so it cross-compiles with CGO_ENABLED=0 into an alpine runtime stage. category: refactor ticket: none --- Dockerfile | 36 ++++++++++++++++++++++++++++------- testutil/promrated/Dockerfile | 19 +++++++++++++----- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index b2c1a028a..75c1853bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,20 @@ -# Container for building Go binary. -FROM golang:1.27.3-trixie AS builder -# Install dependencies -RUN apt-get update && apt-get install -y --no-install-recommends build-essential git +# Container for building Go binary. It always runs on the build platform and +# cross-compiles for the target platform, so multi-platform builds don't compile +# under QEMU emulation. +FROM --platform=$BUILDPLATFORM golang:1.27.3-trixie AS builder +ARG BUILDARCH +ARG TARGETOS +ARG TARGETARCH +# Install dependencies, plus a cgo cross compiler when the target arch differs +# from the build arch (herumi bls requires cgo). +RUN apt-get update && apt-get install -y --no-install-recommends build-essential git \ + && if [ "$TARGETARCH" != "$BUILDARCH" ]; then \ + case "$TARGETARCH" in \ + arm64) apt-get install -y --no-install-recommends gcc-aarch64-linux-gnu libc6-dev-arm64-cross ;; \ + amd64) apt-get install -y --no-install-recommends gcc-x86-64-linux-gnu libc6-dev-amd64-cross ;; \ + *) echo "unsupported TARGETARCH=$TARGETARCH" && exit 1 ;; \ + esac; \ + fi # Prep and copy source WORKDIR /app/charon @@ -13,12 +26,18 @@ ARG GO_BUILD_FLAG ENV GO_BUILD_FLAG=${GO_BUILD_FLAG} RUN echo "Building with GO_BUILD_FLAG='${GO_BUILD_FLAG}'" -# Build with Go module and Go build caches. +# Build with Go module and Go build caches (the build cache keys entries by +# GOARCH, so both target arches can share it). RUN \ --mount=type=cache,target=/go/pkg \ --mount=type=cache,target=/root/.cache/go-build \ - go build -o charon "${GO_BUILD_FLAG}" . -RUN echo "Built charon version=$(./charon version)" + if [ "$TARGETARCH" != "$BUILDARCH" ]; then \ + case "$TARGETARCH" in \ + arm64) export CC=aarch64-linux-gnu-gcc ;; \ + amd64) export CC=x86_64-linux-gnu-gcc ;; \ + esac; \ + fi \ + && CGO_ENABLED=1 GOOS="$TARGETOS" GOARCH="$TARGETARCH" go build -o charon "${GO_BUILD_FLAG}" . # Copy final binary into light stage. FROM debian:trixie-slim @@ -33,6 +52,9 @@ ARG GITHUB_SHA=local ENV GITHUB_SHA=${GITHUB_SHA} COPY --from=builder /app/charon/charon /usr/local/bin/ +# Sanity check the binary on the target platform (the builder can't run a +# cross-compiled binary). +RUN version="$(/usr/local/bin/charon version)" && echo "Built charon version=${version}" # Don't run container as root ENV USER=charon diff --git a/testutil/promrated/Dockerfile b/testutil/promrated/Dockerfile index 361867069..3d48e8442 100644 --- a/testutil/promrated/Dockerfile +++ b/testutil/promrated/Dockerfile @@ -1,14 +1,23 @@ -FROM golang:1.27.3-alpine AS builder +# Build on the build platform and cross-compile for the target platform, so +# multi-platform builds don't compile under QEMU emulation. promrated has no cgo +# dependencies, so a pure Go build cross-compiles without a C toolchain. +FROM --platform=$BUILDPLATFORM golang:1.27.3-alpine AS builder -# Install dependencies -RUN apk add --no-cache build-base git +# Install dependencies (git for VCS build info) +RUN apk add --no-cache git WORKDIR /app COPY . . -# Build with Go module and Go build caches. -RUN go build -o promrated github.com/obolnetwork/charon/testutil/promrated/promrated +ARG TARGETOS +ARG TARGETARCH +RUN CGO_ENABLED=0 GOOS="$TARGETOS" GOARCH="$TARGETARCH" \ + go build -o promrated github.com/obolnetwork/charon/testutil/promrated/promrated + +FROM alpine:3.24 + +COPY --from=builder /app/promrated /app/promrated # Don't run container as root ENV USER=promrated From 7600f72e185e6acf160e9b0dd04254ddbc748163 Mon Sep 17 00:00:00 2001 From: kalo <24719519+KaloyanTanev@users.noreply.github.com> Date: Fri, 30 Oct 2026 11:05:28 +0200 Subject: [PATCH 2/2] Dockerfile: echo target os and arch --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 75c1853bc..1cae15c74 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ COPY . . # Populate GO_BUILD_FLAG with a build arg to provide an optional go build flag. ARG GO_BUILD_FLAG ENV GO_BUILD_FLAG=${GO_BUILD_FLAG} -RUN echo "Building with GO_BUILD_FLAG='${GO_BUILD_FLAG}'" +RUN echo "Building for ${TARGETOS}/${TARGETARCH} on ${BUILDARCH} with GO_BUILD_FLAG='${GO_BUILD_FLAG}'" # Build with Go module and Go build caches (the build cache keys entries by # GOARCH, so both target arches can share it).