How to Build Multi-Architecture Container Images (arm64/amd64)

You can build multi-architecture container images using the Apple Container CLI by passing the --arch flag multiple times during the build command, which instructs the builder shim to create distinct variants for both arm64 and amd64 that are stored under a single OCI manifest name.

Apple Container is an open-source container runtime designed for macOS that simplifies creating and managing Linux containers on Apple Silicon. When you need to build multi-architecture container images that support both ARM64 and AMD64 processors, the CLI provides native multiplatform support through repeatable architecture flags that interface with the underlying builder shim.

Understanding the Architecture Flag

According to the source code in Sources/Services/ContainerAPIService/Client/Arch.swift (lines 18-33), the CLI parses the --arch arguments into an array of Arch enum values. This enum validates the supported architectures—arm64 and amd64—and converts string inputs into typed values used throughout the system to populate ContainerizationOCI.Platform structs.

When building, you specify architectures by repeating the flag:

container build --arch arm64 --arch amd64 --tag myimage:latest --file Dockerfile .

The Build Process

The container build command delegates architecture handling to the BuilderStart class in Sources/ContainerCommands/Builder/BuilderStart.swift (lines 32-69). The BuilderStart.start method receives the list of architectures and forwards them to the builder shim, which is registered as the entry point in Sources/ContainerCommands/Builder/Builder.swift.

The builder shim runs in a lightweight VM capable of hosting both arm64 and amd64 userspaces. For each specified architecture, the shim creates a distinct image layer. On Apple Silicon hosts, the amd64 variant executes under Rosetta, though VM isolation ensures each variant sees native kernel and library sets for its target architecture.

Pushing and Running Multi-Architecture Images

The resulting image is an OCI-compliant multi-arch manifest (manifest list) containing each variant's platform field (os: "linux", architecture: "arm64" or "amd64"). When you push the image:

container image push registry.example.com/myapp:latest

Both variants upload automatically because the manifest lists both platform variants.

To run a specific variant, use the --arch flag as documented in docs/command-reference.md:


# Run the ARM-64 variant (native on Apple Silicon)

container run --arch arm64 --rm myapp:latest uname -m

# Run the x86-64 variant (executed under Rosetta on Apple Silicon)

container run --arch amd64 --rm myapp:latest uname -m

If you omit the --arch flag, the runtime defaults to the host architecture (arm64 on Apple Silicon).

Complete Workflow Example

Here is the complete workflow from building to running multi-architecture images, as documented in docs/how-to.md (lines 63-71):


# Build an image containing both ARM-64 and x86-64 variants

container build \
    --arch arm64 \
    --arch amd64 \
    --tag registry.example.com/fido/web-test:latest \
    --file Dockerfile .

# Push the multi-arch image to a registry (single command uploads both variants)

container image push registry.example.com/fido/web-test:latest

# Run the ARM-64 variant (native on Apple Silicon)

container run --arch arm64 --rm registry.example.com/fido/web-test:latest uname -a

# Linux … aarch64 GNU/Linux

# Run the x86-64 variant (executed under Rosetta on Apple Silicon)

container run --arch amd64 --rm registry.example.com/fido/web-test:latest uname -a

# Linux … x86_64 GNU/Linux

Summary

  • Use --arch flags: Pass --arch arm64 --arch amd64 to the container build command to create multi-architecture container images with Apple Container.
  • Parsed into Arch enum: The CLI converts architecture strings to the Arch enum defined in Sources/Services/ContainerAPIService/Client/Arch.swift.
  • Forwarded by BuilderStart: The BuilderStart.start method in Sources/ContainerCommands/Builder/BuilderStart.swift passes the architecture list to the builder shim.
  • OCI manifest list: The output is a single image name containing a manifest list with platform-specific variants.
  • Rosetta support: AMD64 variants run transparently on Apple Silicon using Rosetta when selected via --arch amd64.

Frequently Asked Questions

How does Apple Container handle amd64 images on Apple Silicon?

When running an amd64 image on Apple Silicon, the runtime automatically uses Rosetta 2 for binary translation. The builder shim executes in a lightweight VM that isolates the amd64 userspace while providing access to x86-64 libraries, allowing seamless execution of Intel binaries on ARM hardware without manual configuration.

What is the default architecture if I omit the --arch flag?

If you do not specify --arch, Apple Container defaults to the host architecture, which is arm64 on Apple Silicon Macs and amd64 on Intel Macs. To create true multi-architecture images that support both platforms simultaneously, you must explicitly pass both --arch arm64 and --arch amd64 during the build process.

Can I build for architectures other than arm64 and amd64?

Currently, Apple Container only supports arm64 and amd64 as defined in the Arch enum in Sources/Services/ContainerAPIService/Client/Arch.swift. The CLI validates inputs against these two values, and the builder shim is configured specifically for these architectures, limiting multi-architecture builds to these platforms.

How does the image manifest store multiple architectures?

Apple Container generates an OCI manifest list where each entry references a platform-specific image layer with corresponding platform fields specifying os and architecture (either "arm64" or "amd64"). This allows a single image name to reference distinct variants, enabling registries to store all architectures together and clients to pull only the variant matching their host or the specific --arch argument.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →