How to Build Multi-Platform Images with Apple Container: A Complete Guide
Use the container build command with repeated --arch flags or the unified --platform flag to generate OCI manifest lists containing multiple platform variants, then push and run specific architectures using the Apple Container CLI.
Apple Container is an open-source Swift-based container runtime that enables developers to build and manage OCI-compliant images on macOS. When you need to distribute applications for both Apple Silicon (arm64) and Intel (x86-64) architectures, the container CLI provides native multi-platform build capabilities through BuildKit integration. This workflow produces a single image reference that contains distinct variants for each target platform.
Understanding Multi-Platform Image Architecture
Multi-platform images (also called manifest lists) bundle multiple architecture-specific variants under a single image reference. When you build multi-platform images with Apple Container, the tool constructs an OCI manifest list containing separate layer sets for each target platform. The BuildKit integration defined in Package.swift orchestrates the cross-platform compilation, ensuring that each architecture receives its own optimized binary layers while sharing a unified manifest structure.
Building Multi-Platform Images
Using the --arch Flag for Multiple Architectures
The simplest method to target multiple platforms uses the --arch flag repeatedly. According to docs/command-reference.md, each --arch entry adds a new variant to the resulting image manifest. The CLI passes these values to BuildKit, which creates distinct image layers for each architecture.
Create a simple Dockerfile in your project directory:
# example-app/Dockerfile
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3
CMD ["python3", "--version"]
Build for both arm64 (Apple Silicon) and amd64 (x86-64):
container build \
--arch arm64 \
--arch amd64 \
--tag ghcr.io/example/multi-platform:latest \
--file example-app/Dockerfile .
Using the --platform Flag for OS/Architecture Combinations
For explicit control over both operating system and architecture, use the unified --platform flag (e.g., linux/arm64). As documented in docs/command-reference.md, the --platform flag takes precedence over both --arch and --os when conflicts arise.
container build \
--platform linux/arm64 \
--platform linux/amd64 \
--tag ghcr.io/example/multi-platform:latest \
--file example-app/Dockerfile .
Verifying Platform Variants
After building, verify that the image contains all requested platform variants using the container image inspect command. This outputs the manifest list details showing each architecture configuration.
container image inspect ghcr.io/example/multi-platform:latest | jq '.variants[].platform'
Expected output shows distinct platform objects:
{
"os": "linux",
"architecture": "arm64"
}
{
"os": "linux",
"architecture": "amd64"
}
Pushing Multi-Platform Images
A single container image push command uploads the entire manifest list along with all platform-specific blobs. The image name is shared by all variants, ensuring that consumers automatically receive the correct architecture for their runtime environment.
container image push ghcr.io/example/multi-platform:latest
The push operation uploads the manifest list and both platform-specific layer sets in a single atomic operation.
Running Specific Platform Variants
When executing containers on Apple Silicon hardware, you can select specific variants using either --arch or --platform with the container run command. The arm64 variant runs natively on Apple Silicon, while the amd64 variant executes under Rosetta translation for x86-64 compatibility.
# Run the arm64 variant (native on Apple Silicon)
container run --arch arm64 ghcr.io/example/multi-platform:latest uname -a
# Run the amd64 variant (executed under Rosetta on Apple Silicon)
container run --arch amd64 ghcr.io/example/multi-platform:latest uname -a
Alternatively, use the platform-specific syntax:
container run --platform linux/arm64 ghcr.io/example/multi-platform:latest uname -a
Configuration Architecture
BuildConfig and Platform Storage
The architecture selections specified via CLI flags are persisted in the BuildConfig class. According to the source code in Sources/ContainerPersistence/ContainerSystemConfig.swift, this Swift model records the list of target platforms for a build, enabling BuildKit to reference the configuration during the compilation phase.
CLI Flag Precedence Rules
The command reference documentation establishes a strict hierarchy for platform selection flags:
--platformtakes highest precedence and overrides both--archand--os--archand--oscan be used independently but are superseded by--platform- Multiple values for
--archare accumulated to form the complete target platform list
Summary
- Apple Container generates OCI manifest lists containing multiple platform variants through BuildKit integration.
- Use repeated
--archflags (e.g.,--arch arm64 --arch amd64) or the unified--platformflag to specify target architectures. - The
BuildConfigclass inSources/ContainerPersistence/ContainerSystemConfig.swiftstores architecture selections during the build process. - A single
container image pushuploads the manifest list and all platform-specific layers simultaneously. - Execute specific variants using
container run --arch <architecture>or--platform <os/arch>, with native execution on Apple Silicon and Rosetta translation for x86-64.
Frequently Asked Questions
What is the difference between --arch and --platform?
The --arch flag specifies only the CPU architecture (e.g., arm64, amd64), while the --platform flag accepts the full OS/architecture combination (e.g., linux/arm64). According to docs/command-reference.md, --platform takes precedence when both are specified, and --arch can be repeated multiple times to target several architectures in one build.
How does Apple Container execute x86-64 images on Apple Silicon?
When you run an amd64 variant on Apple Silicon using container run --arch amd64, the container executes under Rosetta translation. The arm64 variant runs natively without translation overhead, while the x86-64 variant automatically uses Apple's Rosetta 2 technology for compatibility.
Where is the target platform configuration stored during builds?
The target platform configuration is stored in the BuildConfig class, defined in Sources/ContainerPersistence/ContainerSystemConfig.swift. This Swift model persists the list of architecture selections specified via CLI flags, allowing BuildKit to reference the complete target configuration throughout the build process.
Can I build for more than two architectures simultaneously?
Yes. You can specify as many architectures as your BuildKit backend supports by repeating the --arch flag for each target. Each occurrence adds a new variant to the manifest list, enabling you to build for arm64, amd64, riscv64, or other supported architectures in a single invocation.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →