Skip to content

Support ARM (arm64) architecture in development tooling #4533

@markmandel

Description

@markmandel

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

  1. 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.

  2. 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.

  3. 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.

  4. 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).

  5. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/build-toolsDevelopment tooling. I.e. pretty much everything in the `build` directory.help wantedWe would love help on these issues. Please come help us!kind/featureNew features for Agones

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions