How to Build Multi-Platform Images (arm64 and amd64) with Container

You can build multi-platform images for arm64 and amd64 by passing multiple --arch flags to container build, which creates a manifest list that the CLI automatically selects from at runtime or when pulling.

The container tool from the Apple open-source repository produces OCI-compatible images that bundle multiple architectures into a single tag. This allows you to build multi-platform images (arm64 and amd64) with container using a straightforward CLI workflow that handles manifest lists automatically.

Building Multi-Platform Images with the --arch Flag

To create an image that supports both Apple Silicon (arm64) and x86-64 (amd64) hosts, specify each target architecture using the --arch flag during the build process. The container build command aggregates these variants into a single manifest list, enabling the same image tag to resolve to different layer sets depending on the host platform.

According to the official how-to documentation in docs/how-to.md (lines 63-71), the build flow requires repeating the --arch flag for each desired platform:

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

This command generates platform-specific image configurations stored internally as ContainerizationOCI.Platform objects, which track the OS and architecture for each variant.

Understanding the Platform Configuration Internals

The multi-platform capability relies on three key components that handle platform definitions, CLI argument parsing, and runtime selection.

Platform Definitions in MachineConfiguration.swift

The underlying data structure for platform information lives in Sources/Services/MachineAPIService/Client/MachineConfiguration.swift (lines 55-95). This file defines the Platform struct used throughout the service to represent operating system and architecture combinations, ensuring consistent handling of arm64 and amd64 variants across the build and runtime pipelines.

CLI Flag Parsing in Flags.swift

When you specify a platform override at runtime, the CLI parses these arguments through Sources/Services/MachineAPIService/Client/Flags.swift (lines 30-31). This logic processes the --platform flag—which accepts values in os/arch[/variant] format—according to the command reference documentation found at docs/command-reference.md (line 155).

Runtime Platform Selection in SnapshotStore.swift

During image unpacking, the server selects the appropriate manifest entry via Sources/Services/ContainerImagesService/Server/SnapshotStore.swift (lines 66-71). The MachineAPIService calls image.descriptor(for: platform) to fetch the correct architecture-specific descriptor from the manifest list, ensuring the host receives the matching variant.

Running and Pushing Multi-Platform Images

Once built, the manifest list allows seamless cross-platform workflows. The container run command automatically selects the variant matching your host architecture, or you can force a specific version using flags.

To run the image with automatic platform selection:

container run --rm registry.example.com/app:latest uname -a

To override the architecture at runtime, use the --arch flag or the --platform flag documented in the command reference:


# Force arm64

container run --arch arm64 --rm registry.example.com/app:latest uname -a

# Force amd64

container run --arch amd64 --rm registry.example.com/app:latest uname -a

Pushing uploads the entire manifest list in one step, making all variants available to any pulling host:

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

Summary

  • Build multi-platform images by repeating the --arch flag for each target architecture (arm64, amd64) during container build.
  • The system creates a manifest list that references architecture-specific images under a single tag.
  • Platform definitions are handled by ContainerizationOCI.Platform in MachineConfiguration.swift (lines 55-95).
  • CLI flags are parsed in Flags.swift (lines 30-31) and runtime selection occurs in SnapshotStore.swift via image.descriptor(for: platform) (lines 66-71).
  • Use --arch or --platform to override automatic platform selection when running images.

Frequently Asked Questions

How do I specify multiple architectures when building with container?

Pass the --arch flag multiple times, once for each architecture. For example, --arch arm64 --arch amd64 builds both variants and bundles them into a single manifest list under your specified tag. The builder produces separate images for each platform and aggregates them into an OCI-compliant manifest list.

Does container automatically select the right architecture at runtime?

Yes. When you execute container run, the CLI inspects the host platform and automatically selects the image variant that matches your architecture. You can override this behavior using the --arch flag to force a specific variant, or use the --platform flag to specify the full platform string.

Where does container store platform information for multi-arch images?

Platform metadata is stored using ContainerizationOCI.Platform objects defined in Sources/Services/MachineAPIService/Client/MachineConfiguration.swift (lines 55-95). During runtime, the specific descriptor for the requested platform is retrieved via image.descriptor(for: platform) in Sources/Services/ContainerImagesService/Server/SnapshotStore.swift (lines 66-71).

Can I push multi-platform images to any OCI-compliant registry?

Yes. The manifest list created by container build follows the OCI image specification. Executing container image push uploads all architecture variants simultaneously, and any OCI-compliant registry can distribute them. When pulling, the client automatically receives the variant matching the host platform.

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 →