How Apple's Container Runtime Works on Apple Silicon Macs: Linux VM Architecture Explained

Apple's container runtime leverages the macOS Virtualization framework to run each container inside a lightweight Linux virtual machine, orchestrated by the RuntimeService actor through a secure XPC service architecture.

The apple/container repository provides a native container runtime for macOS that uses Apple Silicon hardware virtualization instead of traditional kernel namespaces. Each container operates within its own Linux VM created via the Virtualization framework, with the runtime exposed as the container-runtime-linux XPC service managed by the container-apiserver launch agent.

Core Architecture Components

The runtime architecture consists of several Swift-based services that bridge the macOS Virtualization framework with container workflows.

Virtualization Framework and VM Management

At the heart of the system lies the Virtualization framework, which creates a VZVirtualMachineManager instance to boot the Linux kernel and container root filesystem. This provides hardware-accelerated virtualization on Apple Silicon M-series CPUs using KVM-compatible virtualization extensions.

In Sources/Services/RuntimeLinux/Server/RuntimeService.swift, the RuntimeService actor instantiates the virtual machine manager and handles the complete lifecycle from bundle creation to shutdown. The service manages VM state transitions using lock.withLock to enforce valid transitions from created to booting and beyond.

XPC Service Communication

The runtime exposes functionality through XPC services for secure inter-process communication. The container-runtime-linux service registers a Mach service using the label format com.apple.container.runtime.<runtime>.<id>, receiving RPCs from the container CLI via the RuntimeClient class.

The RuntimeClient implementation in Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift constructs the Mach service identifier and establishes the XPC connection to the runtime service.

Networking and Persistence

The ContainerNetworkClient obtains network attachments from the container-network-vmnet helper and passes them to the VM, setting up a virtual NIC inside the guest that connects to the host's vmnet network. This logic appears in the networkBootstrapInfos loop within RuntimeService.swift.

Configuration persists through ContainerPersistence, which stores settings in runtime-configuration.json. The RuntimeConfiguration struct in Sources/Services/Runtime/RuntimeClient/RuntimeConfiguration.swift handles reading and writing VM parameters including kernel path, memory allocation, and CPU count.

Apple Silicon Requirements and Nested Virtualization

Running containers on Apple Silicon involves specific hardware requirements and optional nested virtualization support.

Hardware Prerequisites

Apple Silicon M3 or later with macOS 15 or later is required for nested virtualization capabilities. The runtime checks for hardware-assisted virtualization support and requires the guest kernel to be built with CONFIG_KVM=y for nested VM functionality.

According to the documentation in docs/container-machine.md and docs/command-reference.md, the --virtualization flag enables KVM device passthrough when the host supports it.

KVM Device Passthrough

When users specify the --virtualization flag, the runtime passes the KVM device (/dev/kvm) into the guest VM. The RuntimeService verifies host kernel support before exposing the device, allowing the guest to run its own nested virtual machines.

The kernel command-line automatically includes security parameters "oops=panic" and "lsm=lockdown,capability,landlock,yama,apparmor" regardless of virtualization mode.

Rosetta Configuration

On Apple Silicon systems, Rosetta translation can be disabled for builds via user configuration in ~/.config/container/config.toml, as documented in docs/how-to.md.

Container Lifecycle: From CLI to Running VM

The container lifecycle follows a structured bootstrap process managed by the RuntimeService actor.

Bootstrap Sequence

  1. CLI Invocation: The user runs container machine create with optional --virtualization. The CLI initializes a RuntimeClient and calls the bootstrap method.

  2. Bundle Preparation: The RuntimeService.bootstrap method in Sources/Services/RuntimeLinux/Server/RuntimeService.swift checks for bundle existence, creates it if missing, and reads the configuration from runtime-configuration.json.

  3. VM Instantiation: The service creates a VZVirtualMachineManager with the specified kernel and root filesystem, acquires the state lock, and allocates network attachments via ContainerNetworkClient.

  4. Endpoint Registration: After starting the VM, the service registers an XPC endpoint via createEndpoint to accept further commands.

Process Execution

Once booted, the CLI issues container runtime start or container machine run. The client sends an XPC createProcess request, and RuntimeService spawns a ProcessInfo inside the VM, returning a PID to the caller.

Shutdown Procedures

The RuntimeService.shutdown method tears down the VM, cleans up networking resources, and removes temporary files, ensuring clean state transitions.

Configuration and Code Examples

Swift Client Implementation

Create a RuntimeClient and bootstrap the VM using the ContainerXPC framework:

import ContainerXPC
import ContainerRuntimeClient

let client = try await RuntimeClient.create(
    id: "myContainer",
    runtime: "linux-sandboxd"
)

let endpointMessage = XPCMessage()
let reply = try await client.createEndpoint(endpointMessage)
let endpoint = reply.get(key: RuntimeKeys.runtimeServiceEndpoint.rawValue)

This mirrors the implementation in RuntimeClient.swift and RuntimeService.swift, establishing the Mach service connection and creating the XPC endpoint for subsequent operations.

CLI Commands for Nested Virtualization

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

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

Verify KVM device availability inside the container:

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

These examples reference the documentation in docs/container-machine.md.

Runtime Configuration File

The runtime-configuration.json file persists VM settings:

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

The RuntimeConfiguration.readRuntimeConfiguration and writeRuntimeConfiguration methods in RuntimeConfiguration.swift manage this persistence layer.

Summary

  • Apple's container runtime uses the macOS Virtualization framework to run containers inside lightweight Linux VMs on Apple Silicon, rather than using kernel namespaces.
  • The RuntimeService actor in Sources/Services/RuntimeLinux/Server/RuntimeService.swift manages the complete VM lifecycle, networking via ContainerNetworkClient, and XPC communication.
  • Apple Silicon M3 or later with macOS 15 or later is required for nested virtualization with KVM device passthrough.
  • The runtime communicates via XPC services using Mach service labels formatted as com.apple.container.runtime.<runtime>.<id>.
  • Configuration persists in runtime-configuration.json, managed by the RuntimeConfiguration struct.

Frequently Asked Questions

What virtualization technology does Apple's container runtime use on Apple Silicon?

The runtime uses the macOS Virtualization framework (VZVirtualMachineManager) to create hardware-accelerated Linux VMs. It leverages the Apple Silicon M-series CPU's virtualization extensions to provide KVM-compatible nested virtualization when running on M3 or later with macOS 15.

How does the container CLI communicate with the runtime service?

The container CLI creates a RuntimeClient that connects to the container-runtime-linux XPC service. This service registers a Mach service with the label com.apple.container.runtime.<runtime>.<id> and exposes methods like bootstrap, createEndpoint, and createProcess for VM lifecycle management.

What are the requirements for running nested virtualization in Apple container machines?

Nested virtualization requires Apple Silicon M3 or later and macOS 15 or later. You must supply a custom kernel built with CONFIG_KVM=y and use the --virtualization flag when creating the machine. The runtime then passes /dev/kvm into the guest VM.

Where does the runtime store VM configuration and state?

The runtime persists configuration in runtime-configuration.json using the ContainerPersistence layer. The RuntimeConfiguration struct in Sources/Services/Runtime/RuntimeClient/RuntimeConfiguration.swift handles serialization of kernel paths, memory settings, CPU count, and Rosetta configuration options.

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 →