# How container build Handles Multi-Architecture Builds Using the --arch Flag

> Learn how apple/container's build command uses the --arch flag to create multi architecture builds. Discover how it combines architectures and OS for efficient manifest lists.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-06-17

---

**The `container build` command aggregates comma-separated architecture values from the `--arch` flag, combines them with the target operating system (defaulting to Linux), and passes a `Set<Platform>` to BuildKit to generate a multi-architecture manifest list.**

The `container build` command in the [apple/container](https://github.com/apple/container) repository provides native support for multi-architecture container images through its `--arch` flag. By transforming user input into platform-specific build configurations, the command enables BuildKit to produce manifest lists containing separate image variants for each requested architecture. This implementation leverages Swift's argument parsing capabilities and sophisticated platform resolution logic to streamline cross-platform container development.

## How the --arch Flag Works in container build

### Option Parsing and Default Values

In [`Sources/ContainerCommands/BuildCommand.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/BuildCommand.swift), the `--arch` flag is implemented as an `@Option` that accepts comma-separated values and can be specified multiple times. The declaration appears at lines 54-62:

```swift
@Option(
    name: .shortAndLong,
    help: ArgumentHelp("Add the architecture type to the build",
                      valueName: "value"),
    transform: { val in val.split(separator: ",").map { String($0) } }
)
var arch: [[String]] = {
    [[Arch.hostArchitecture().rawValue]]
}()

```

The `transform` closure splits comma-separated input into individual strings, while the default closure initializes the value to the host architecture using `Arch.hostArchitecture().rawValue`. When users specify `--arch` multiple times, each occurrence appends a new sub-array, resulting in a nested array structure like `[["arm64"], ["amd64"]]` for the invocation `--arch arm64 --arch amd64`.

### Platform Resolution Logic

The platform resolution occurs in [`BuildCommand.swift`](https://github.com/apple/container/blob/main/BuildCommand.swift) between lines 423-447. The command evaluates platform specifications in strict priority order:

1. **Explicit `--platform` flags** (highest priority)
2. **`CONTAINER_DEFAULT_PLATFORM` environment variable** (fallback)
3. **Combined `--os` and `--arch` values** (default when no other platform specified)

When falling back to the OS/arch combination, the code iterates through all collected architecture values:

```swift
for o in (self.os.flatMap { $0 }) {
    for a in (self.arch.flatMap { $0 }) {
        guard let platform = try? Platform(from: "\(o)/\(a)") else {
            throw ValidationError("invalid os/architecture combination \(o)/\(a)")
        }
        results.insert(platform)
    }
}

```

This creates a `Platform` instance for every OS-architecture pair, defaulting to `linux` when `--os` is not specified. The resulting `Set<Platform>` eliminates duplicates while preserving all unique platform combinations requested by the user.

### BuildKit Integration for Multi-Arch Output

After platform resolution, the command passes the platform set to the builder configuration at lines 664-670:

```swift
let config = Builder.BuildConfig(
    …,
    platforms: [Platform](platforms),
    …
)

```

BuildKit receives this array and constructs a multi-architecture manifest list, building each variant in parallel when possible. The final image contains separate layers for each architecture under a single tag, enabling runtime selection via the `--arch` flag in `container run`.

## Practical Examples for Multi-Architecture Builds

You can specify architectures using multiple flags or comma-separated values:

**Multiple flag approach:**

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

```

**Comma-separated values:**

```bash
container build \
    --arch arm64,amd64 \
    --tag registry.example.com/app:latest \
    .

```

**Running specific variants:**

```bash
container run --arch arm64 registry.example.com/app:latest uname -a
container run --arch amd64 registry.example.com/app:latest uname -a

```

## Key Source Files and Implementation Details

Understanding the multi-architecture implementation requires examining these specific files:

- **[`Sources/ContainerCommands/BuildCommand.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/BuildCommand.swift)**: Contains the `BuildCommand` class, `@Option` declaration for `--arch`, platform resolution logic (lines 423-447), and BuildKit configuration (lines 664-670).
- **[`Tests/CLITests/Subcommands/Build/CLIBuilderTest.swift`](https://github.com/apple/container/blob/main/Tests/CLITests/Subcommands/Build/CLIBuilderTest.swift)**: Provides unit test coverage for the `--arch` flag, including test cases with comma-separated values like `["--arch", "amd64,arm64"]`.
- **[`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md)**: Documents user-facing examples of multi-platform builds using `--arch` (lines 67-71).
- **[`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md)**: References the `--arch` flag in the command documentation.

## Summary

- The `--arch` flag accepts comma-separated values and can be specified multiple times, with a default value matching the host architecture.
- Platform resolution follows a strict priority: `--platform` > `CONTAINER_DEFAULT_PLATFORM` > combined `--os`/`--arch`.
- The command generates a `Set<Platform>` from OS-architecture pairs and passes it to BuildKit via `Builder.BuildConfig`.
- BuildKit produces a manifest list containing discrete image variants for each requested architecture.
- Unit tests in [`CLIBuilderTest.swift`](https://github.com/apple/container/blob/main/CLIBuilderTest.swift) validate the flag parsing and platform resolution behavior.

## Frequently Asked Questions

### Can I mix comma-separated and multiple --arch flags in the same command?

Yes. The transform closure splits each flag's value by commas, and multiple flag occurrences append to the nested array. Both `--arch arm64,amd64` and `--arch arm64 --arch amd64` produce equivalent platform sets after the flattening operation in the resolution logic.

### What happens if I don't specify the --arch flag?

When omitted, the default closure initializes the architecture to the host's native architecture using `Arch.hostArchitecture().rawValue`. The build produces a single-architecture image for the detected host platform, ensuring compatibility with the machine running the command.

### Does the --arch flag override the --platform flag?

No. The platform resolution logic explicitly checks `--platform` first (lines 423-427 in [`BuildCommand.swift`](https://github.com/apple/container/blob/main/BuildCommand.swift)). If `--platform` is present, the command ignores both `--os` and `--arch` values entirely, using only the explicitly specified platform string.

### How does the container tool validate architecture combinations?

During the resolution loop (lines 436-440), the command attempts to initialize a `Platform` instance with the format `"\(os)/\(architecture)"`. If the combination is invalid, it throws a `ValidationError` with the message "invalid os/architecture combination" before reaching BuildKit, preventing wasted build cycles on unsupported platforms.