Summary
Agones already produces multi-arch production images (amd64 + arm64) using docker buildx, but the development tooling containers are hardcoded to download AMD64 binaries. Developers on ARM64 hosts (Apple Silicon M-series, Ampere, AWS Graviton, etc.) must run the build container under x86_64 emulation, which is slow and error-prone.
The goal of this issue is to make all build/development containers natively runnable on ARM64.
Affected Files
build/build-image/Dockerfile
The primary build container downloads the following tools hardcoded to linux-amd64 / x86_64:
- Go (
linux-amd64.tar.gz) — line 34
- kubectl (
bin/linux/amd64/kubectl) — line 58
- Helm (
helm-...-linux-amd64.tar.gz) — line 69
- Hugo (amd64 archive) — line ~101
- htmltest (amd64 archive) — line ~102
- Terraform (amd64 zip) — line ~103
build/e2e-image/Dockerfile
- Go (
linux-amd64.tar.gz) — line 19
- kubectl (
bin/linux/amd64/kubectl) — line 26
- Helm (
helm-...-linux-amd64.tar.gz) — line 32
build/build-sdk-images/go/Dockerfile
- Go (
linux-amd64.tar.gz) — line 26
build/build-sdk-images/restapi/Dockerfile
- Go (
linux-amd64.tar.gz) — line 26
build/build-sdk-images/rust/Dockerfile
- rustup-init (
x86_64-unknown-linux-gnu/rustup-init) — line 26
build/Makefile
- Lines 221–225: ARM host detection explicitly forces
--platform linux/x86_64 when pulling/running the build container, preventing native ARM64 execution.
What "Done" Looks Like
- All Dockerfiles detect the target architecture at build time (using
ARG TARGETARCH / ARG TARGETPLATFORM with Docker BuildKit) and download the appropriate binary for amd64 or arm64.
- The build container images are built and pushed as multi-arch manifests (for verification and publishing purposes).
- When using the build container locally for development, only the native host architecture is built — no double-building. This keeps local iteration fast.
- The
Makefile platform-forcing logic (lines 221–225) is updated so that ARM64 hosts automatically use a native ARM64 build container.
Note: It is acceptable to make breaking changes to how the development tooling currently works if doing so makes it easier to properly support multiple architectures. Don't feel constrained by the current implementation.
Getting Started
-
Understand the existing multi-arch pattern: Look at how the Agones runtime images already handle linux/amd64 and linux/arm64 in build/Makefile (search for WITH_ARM64, build-controller-image, and the docker buildx calls). The same approach applies here.
-
Use Docker TARGETARCH build arg: In each Dockerfile, replace hardcoded architecture strings with the BuildKit built-in TARGETARCH (values: amd64, arm64). Example pattern:
ARG TARGETARCH
RUN curl -L https://dl.google.com/go/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz | tar -xz -C /usr/local
For tools that use different naming conventions (e.g., Rust uses x86_64-unknown-linux-gnu vs aarch64-unknown-linux-gnu), you'll need a small RUN case statement to map TARGETARCH to the tool-specific triplet.
-
Build the updated image for both platforms using docker buildx build --platform linux/amd64,linux/arm64 . to verify both succeed. This multi-arch build is for verification and publishing only.
-
Update build/Makefile to detect the host architecture and build/pull only the matching image for local development. Remove the forced --platform linux/x86_64 override on ARM hosts (lines 221–225).
-
Test locally on an ARM64 machine (or with QEMU emulation) by running a build target end-to-end.
Open Question: Output Image Architecture Defaults
Currently WITH_ARM64=1 is the default, meaning both amd64 and arm64 output images are built. However, because the build container is forced to AMD64 today, all output images are effectively cross-compiled from an emulated AMD64 environment regardless.
Once the build container runs natively on ARM, it's worth considering:
- Should a developer on an ARM64 host default to building only
arm64 output images (skipping unnecessary cross-compilation for faster local iteration)?
- Is
WITH_ARM64=1 the right flag for this, or should there be a more ergonomic default that just builds for the native host arch?
This is in scope for this issue if contributors want to tackle it, or it can be a follow-up.
References
Summary
Agones already produces multi-arch production images (amd64 + arm64) using
docker buildx, but the development tooling containers are hardcoded to download AMD64 binaries. Developers on ARM64 hosts (Apple Silicon M-series, Ampere, AWS Graviton, etc.) must run the build container under x86_64 emulation, which is slow and error-prone.The goal of this issue is to make all build/development containers natively runnable on ARM64.
Affected Files
build/build-image/DockerfileThe primary build container downloads the following tools hardcoded to
linux-amd64/x86_64:linux-amd64.tar.gz) — line 34bin/linux/amd64/kubectl) — line 58helm-...-linux-amd64.tar.gz) — line 69build/e2e-image/Dockerfilelinux-amd64.tar.gz) — line 19bin/linux/amd64/kubectl) — line 26helm-...-linux-amd64.tar.gz) — line 32build/build-sdk-images/go/Dockerfilelinux-amd64.tar.gz) — line 26build/build-sdk-images/restapi/Dockerfilelinux-amd64.tar.gz) — line 26build/build-sdk-images/rust/Dockerfilex86_64-unknown-linux-gnu/rustup-init) — line 26build/Makefile--platform linux/x86_64when pulling/running the build container, preventing native ARM64 execution.What "Done" Looks Like
ARG TARGETARCH/ARG TARGETPLATFORMwith Docker BuildKit) and download the appropriate binary foramd64orarm64.Makefileplatform-forcing logic (lines 221–225) is updated so that ARM64 hosts automatically use a native ARM64 build container.Getting Started
Understand the existing multi-arch pattern: Look at how the Agones runtime images already handle
linux/amd64andlinux/arm64inbuild/Makefile(search forWITH_ARM64,build-controller-image, and thedocker buildxcalls). The same approach applies here.Use Docker
TARGETARCHbuild arg: In each Dockerfile, replace hardcoded architecture strings with the BuildKit built-inTARGETARCH(values:amd64,arm64). Example pattern:For tools that use different naming conventions (e.g., Rust uses
x86_64-unknown-linux-gnuvsaarch64-unknown-linux-gnu), you'll need a smallRUNcase statement to mapTARGETARCHto the tool-specific triplet.Build the updated image for both platforms using
docker buildx build --platform linux/amd64,linux/arm64 .to verify both succeed. This multi-arch build is for verification and publishing only.Update
build/Makefileto detect the host architecture and build/pull only the matching image for local development. Remove the forced--platform linux/x86_64override on ARM hosts (lines 221–225).Test locally on an ARM64 machine (or with QEMU emulation) by running a build target end-to-end.
Open Question: Output Image Architecture Defaults
Currently
WITH_ARM64=1is the default, meaning bothamd64andarm64output images are built. However, because the build container is forced to AMD64 today, all output images are effectively cross-compiled from an emulated AMD64 environment regardless.Once the build container runs natively on ARM, it's worth considering:
arm64output images (skipping unnecessary cross-compilation for faster local iteration)?WITH_ARM64=1the right flag for this, or should there be a more ergonomic default that just builds for the native host arch?This is in scope for this issue if contributors want to tackle it, or it can be a follow-up.
References
build/Makefilelines 48, 81, 172–173, 276–285, 550–563