How Apple Container Runtime Works on Apple Silicon: Architecture and Implementation

Apple's container runtime executes Linux containers inside lightweight, hardware-accelerated virtual machines using the macOS Virtualization framework, orchestrated by the RuntimeService actor via secure XPC service calls.

The apple/container repository provides Apple's open-source container runtime, which leverages Apple Silicon's hardware-assisted virtualization capabilities to run Linux workloads. Unlike traditional container engines that share the host kernel, this runtime boots a full Linux VM for each container, providing enhanced isolation while maintaining near-native performance through the Virtualization framework. The architecture centers on the RuntimeService actor, which manages the entire lifecycle from VM creation to process execution.

Core Architecture

Virtualization Framework Integration

At the foundation of the Apple container runtime is the VZVirtualMachineManager from the macOS Virtualization framework. According to the source code in Sources/Services/RuntimeLinux/Server/RuntimeService.swift, the runtime instantiates this manager to boot a Linux kernel and mount the container's root filesystem. This approach provides hardware-accelerated virtualization on Apple Silicon, utilizing the M-series CPU's virtualization extensions (KVM) to run the guest Linux environment.

XPC Service Layer

The runtime operates as an XPC service named container-runtime-linux, launched by the container-apiserver launch agent. As implemented in Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift, the service registers a Mach service (com.apple.container.runtime.<runtime>.<id>) to enable secure, sandboxed inter-process communication between the container CLI and the runtime backend. This design isolates the VM management logic from the user-facing CLI, improving security and stability.

RuntimeService Actor

The RuntimeService actor serves as the heart of the runtime. Located in Sources/Services/RuntimeLinux/Server/RuntimeService.swift, this Swift actor handles critical XPC routes including createEndpoint, start, stop, state, and statistics. The bootstrap method (lines 31-53) performs the following sequence:

  1. Verifies the bundle exists or creates it.
  2. Reads the kernel and initial filesystem configuration.
  3. Instantiates VZVirtualMachineManager with the specified resources.
  4. Uses lock.withLock to enforce atomic state transitions from created to booting.
  5. Allocates network attachments via ContainerNetworkClient.
  6. Registers the XPC endpoint and starts the VM.

Networking and Persistence

Network connectivity is established through the ContainerNetworkClient, which obtains a virtual network attachment from the container-network-vmnet helper and wires it to the host's vmnet framework. This creates a virtual NIC inside the guest VM.

Configuration persistence is handled by ContainerPersistence and defined in Sources/Services/Runtime/RuntimeClient/RuntimeConfiguration.swift. The runtime stores VM settings—including kernel path, memory allocation, CPU count, and filesystem location—in a runtime-configuration.json file, enabling state recovery across service restarts.

Apple Silicon Requirements

Hardware Prerequisites

Running the Apple container runtime with full virtualization features requires Apple Silicon M3 or later with macOS 15 or later. According to docs/container-machine.md (line 79), these requirements are mandatory for nested virtualization support, which allows the guest Linux VM to run its own KVM workloads.

Nested Virtualization Implementation

When the user specifies the --virtualization flag (documented in docs/command-reference.md, lines 1087-1221), the runtime performs additional setup:

  • Passes the KVM device (/dev/kvm) into the guest VM.
  • Sets kernel command-line arguments to enable KVM ("oops=panic" and "lsm=lockdown,capability,landlock,yama,apparmor").
  • Verifies the host kernel supports KVM before exposing the device.

The guest kernel must be compiled with CONFIG_KVM=y. The default runtime kernel does not include this configuration, so users must supply a custom kernel path via the --kernel flag.

Rosetta Configuration

On Apple Silicon, the runtime respects Rosetta settings for x86_64 binary translation. Users can disable Rosetta for builds by modifying ~/.config/container/config.toml, as noted in docs/how-to.md (line 676). This allows native ARM64 execution without translation overhead.

Container Lifecycle Flow

Bootstrap Sequence

The lifecycle begins when the user executes container machine create or similar commands:

  1. CLI → XPC: The container CLI initializes a RuntimeClient and connects to the Mach service.
  2. Bundle Creation: RuntimeService.bootstrap checks for the existence of the bundle at the configured path and creates it if necessary.
  3. VM Instantiation: The service reads runtime-configuration.json and initializes VZVirtualMachineManager with the specified kernel and root filesystem.
  4. Network Setup: ContainerNetworkClient acquires a network attachment from the vmnet helper.
  5. Initialization: The VM boots, and the service registers the XPC endpoint for receiving further commands.

Process Execution

To run a command inside the container, the CLI sends a createProcess XPC request. RuntimeService creates a ProcessInfo record, spawns the process inside the running VM, and returns a PID to the caller. This mechanism allows the host CLI to interact with processes running inside the isolated Linux environment.

Shutdown

The shutdown method in RuntimeService handles teardown by stopping the VM, releasing network resources, and cleaning up temporary files. This ensures proper resource deallocation and prevents orphaned virtual machines.

Code Examples

Swift Client Implementation

The following Swift code demonstrates creating a RuntimeClient and establishing communication with the runtime service:

import ContainerXPC
import ContainerRuntimeClient

let client = try await RuntimeClient.create(
    id: "myContainer",           // Unique container ID
    runtime: "linux-sandboxd"   // Runtime name used in Mach service label
)

// Ask the runtime service to create an XPC endpoint
let endpointMessage = XPCMessage()
let reply = try await client.createEndpoint(endpointMessage)
let endpoint = reply.get(key: RuntimeKeys.runtimeServiceEndpoint.rawValue)

// Now you can send further commands (e.g., start a process) over this endpoint.

This mirrors the logic in RuntimeClient.create and RuntimeService.createEndpoint.

CLI with Nested Virtualization

To create a container machine with KVM support on Apple Silicon M3 or later:


# Create a container machine with KVM support

container machine create \
    --virtualization \
    --kernel /path/to/vmlinux-kvm \
    --name kvm-dev \
    alpine:latest

# Verify that /dev/kvm is present inside the VM

container machine run -n kvm-dev -- ls -l /dev/kvm

Documentation source: docs/container-machine.md.

Runtime Configuration File

The runtime persists settings in runtime-configuration.json:

{
  "path": "/var/containers/myContainer",
  "initialFilesystem": "/var/containers/myContainer/rootfs",
  "kernel": "/path/to/vmlinux-kvm",
  "containerConfiguration": { "rosetta": false, "ssh": true },
  "runtimeData": null
}

This file is read by RuntimeConfiguration.readRuntimeConfiguration and written by writeRuntimeConfiguration in Sources/Services/Runtime/RuntimeClient/RuntimeConfiguration.swift.

Summary

  • Apple container runtime runs each container inside a dedicated Linux VM using the macOS Virtualization framework and VZVirtualMachineManager.
  • Communication occurs via the container-runtime-linux XPC service, with the RuntimeService actor managing VM lifecycle, networking, and process execution.
  • Apple Silicon M3 or later with macOS 15+ is required for nested virtualization, which passes /dev/kvm into the guest when using the --virtualization flag.
  • Configuration persists in runtime-configuration.json, while network attachments are managed through ContainerNetworkClient and the vmnet framework.
  • The bootstrap method in RuntimeService.swift (lines 31-53) orchestrates VM creation, state transitions, and endpoint registration.

Frequently Asked Questions

What hardware is required to run Apple's container runtime with nested virtualization?

Nested virtualization requires Apple Silicon M3 or later running macOS 15 or later. These specifications ensure the host supports the Virtualization framework features necessary for passing the KVM device (/dev/kvm) into the guest VM. The guest kernel must also be compiled with CONFIG_KVM=y.

How does the container CLI communicate with the runtime service?

The CLI communicates through XPC (Inter-Process Communication). The RuntimeClient class in Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift constructs a Mach service label (com.apple.container.runtime.<runtime>.<id>) and sends messages to the container-runtime-linux XPC service. The RuntimeService actor receives these calls and manages the VM accordingly.

Where does the runtime store VM configuration and state?

Configuration is stored in runtime-configuration.json within the container bundle. The ContainerPersistence class and RuntimeConfiguration struct in Sources/Services/Runtime/RuntimeClient/RuntimeConfiguration.swift handle reading and writing this file, preserving settings such as kernel path, memory limits, CPU count, and filesystem locations across restarts.

Can I disable Rosetta translation for builds on Apple Silicon?

Yes. You can disable Rosetta translation by setting the appropriate option in ~/.config/container/config.toml, as documented in docs/how-to.md (line 676). This forces the runtime to use native ARM64 execution paths instead of x86_64 emulation, potentially improving build performance for native Apple Silicon workloads.

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 →