Skip to content

fix(docker): build CGO images on the target platform - #60

Merged
ASafaeirad merged 1 commit into
mainfrom
worktree-floating-stargazing-umbrella
Aug 8, 2026
Merged

fix(docker): build CGO images on the target platform#60
ASafaeirad merged 1 commit into
mainfrom
worktree-floating-stargazing-umbrella

Conversation

@ASafaeirad

Copy link
Copy Markdown
Member

Problem

The Build and push Docker image step in docker-publish fails on the linux/arm64 leg:

ERROR: failed to solve: process "/bin/sh -c CGO_ENABLED=1 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build ..." did not complete successfully: exit code: 1

The builder stage is pinned to --platform=$BUILDPLATFORM (amd64 on GitHub runners) while setting GOARCH=${TARGETARCH} with CGO_ENABLED=1. gorm.io/driver/sqlite pulls in github.com/mattn/go-sqlite3, which is C code, so the arm64 leg invokes the builder's native amd64 gcc for an arm64 target. golang:alpine ships no cross toolchain, so it exits 1.

The amd64 leg succeeds, which is why the single-arch docker-verify job stayed green and the break only surfaced at publish time.

Changes

  • docker/alpine, docker/pr-build, docker/alpine.debug: drop --platform=$BUILDPLATFORM from the builder stage so it runs on the target platform, under the QEMU emulation docker/setup-qemu-action already installs. CGO then uses a matching native toolchain.
  • Same three files: scope the Go module/build cache mounts with id=...-${TARGETOS}-${TARGETARCH}. Both platform legs now compile real object code and would otherwise share and thrash a single /go/pkg/mod and /root/.cache/go-build.
  • .github/workflows/ci.yml: raise the docker-publish timeout from 30 to 60 minutes, since the emulated arm64 build is substantially slower than the cross-compile it replaces.

docker/goreleaser and release.yml are unaffected — that path copies prebuilt amd64 binaries rather than compiling in the image.

Verification

docker build -f docker/alpine . succeeds locally (builder step ~65s). The arm64 leg was not built locally: this machine has no QEMU binfmt handlers registered and installing them changes host state, so that leg is left to CI.

Alternative considered

Keeping the amd64 builder and adding a cross toolchain (e.g. zig cc) would build faster but adds a non-trivial dependency. The emulated build is the lower-risk change and matches the CGO_ENABLED=1 assumption already baked into .goreleaser.yaml.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Tta36PzgyAeGrZ6NdKiqEj

The builder stages were pinned to $BUILDPLATFORM while setting
GOARCH=${TARGETARCH} with CGO_ENABLED=1. Since gorm.io/driver/sqlite
depends on the cgo-based mattn/go-sqlite3, the linux/arm64 leg of the
multi-arch publish invoked the amd64 runner's native gcc for an arm64
target and failed; golang:alpine ships no cross toolchain. Only the
single-arch amd64 verification job passed, which hid the break until
the publish step.

Drop --platform=$BUILDPLATFORM so the builder runs on the target
platform under the QEMU emulation the workflow already sets up, and
scope the module/build cache mounts per GOOS/GOARCH now that both legs
compile real object code. Raise the docker-publish timeout to 60
minutes to accommodate the slower emulated arm64 build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tta36PzgyAeGrZ6NdKiqEj
@ASafaeirad
ASafaeirad merged commit c5d903f into main Aug 8, 2026
7 checks passed
@ASafaeirad
ASafaeirad deleted the worktree-floating-stargazing-umbrella branch August 8, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant