How container-apiserver Coordinates XPC Helpers for Images, Networking, and Runtime
The container-apiserver acts as the central XPC server that loads specialized helper binaries as plugins—container-core-images for OCI image operations, container-network-vmnet for VM networking, and container-runtime-linux for container execution—routing client requests to the appropriate helper while maintaining isolated process boundaries for security and stability.
The container-apiserver serves as the launch agent orchestrating the container stack on macOS in the apple/container repository. When initiated via container system start, it establishes an XPC server identified as com.apple.container.apiserver and registers routes that delegate to specific helper processes. This architecture isolates privileged operations across distinct binaries while presenting a unified API surface to clients.
Architecture Overview
In Sources/APIServer/APIServer+Start.swift, the apiserver initializes an XPCServer with the identifier com.apple.container.apiserver and registers routes such as containerList, containerCreate, and networkCreate. Rather than implementing container logic directly, the apiserver loads plugins that implement the actual service logic for images, networking, and runtime.
All communication is mediated by the ContainerXPC framework, which provides the underlying transport for inter-process RPCs. The apiserver forwards client requests to the appropriate helper and aggregates results, ensuring that a failure in one helper does not compromise the entire system.
Image Management via XPC
The Image Management responsibility is handled by the container-core-images binary, which exposes the XPC service com.apple.container.core.container-core-images. This helper implements the content-store, OCI pull/push operations, and image-layer handling.
At startup, the apiserver loads the CoreImages plugin through ImagesHelper.swift located in Sources/Plugins/CoreImages/ImagesHelper.swift. The plugin registers its routes with the apiserver’s XPC server, allowing the ContainerAPI client to issue image-related RPCs:
imagePullimageListimagePush
When a client requests an image that is not present locally, the apiserver forwards the request to the image helper, which contacts the remote registry and writes content to the local store.
Networking Coordination
The Networking layer utilizes the container-network-vmnet binary, providing a virtual network backed by macOS vmnet. This helper handles subnet allocation, NAT, and DNS for containers, exposing the XPC service com.apple.container.network.vmnet.
In APIServer+Start.swift, the initializeNetworksService method loads the Network plugin (NetworkHelper.swift). The service registers routes including:
networkCreatenetworkListnetworkDelete
When a container is created, the apiserver asks the network helper for an IP address and subnet via the allocate or lookup routes. The apiserver stores the resulting XPCClientSession for later use, ensuring the container retains its network configuration throughout its lifecycle.
Runtime Lifecycle Management
The Runtime operations are handled by container-runtime-linux, with one instance spawned per container. This binary exposes the XPC service com.apple.container.runtime.linux and implements lifecycle RPCs including bootstrap, start, stop, exec, and stats.
When processing a containerCreate request, the apiserver spawns a new container-runtime-linux helper and establishes an XPC client via RuntimeClient.swift in Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift. The helper returns an XPC endpoint that the apiserver caches and re-uses for the lifetime of the container.
All subsequent container-specific actions—containerStartProcess, containerKill, containerStats—are forwarded over this persistent connection to the runtime helper.
End-to-End Container Launch Flow
The coordination between helpers follows a strict sequence when launching a container:
-
Start the system –
container system startlaunchescontainer-apiserver. -
Load plugins – The apiserver’s
initializePluginLoaderdiscovers the three helper binaries and loads them as launch-agents. -
Create a network – The apiserver calls the network helper’s
allocateroute to reserve an IP and subnet. -
Pull images – If the requested image is absent, the apiserver invokes the image helper’s
pullroute, which downloads layers to the local content store. -
Spawn runtime – The apiserver launches a
container-runtime-linuxhelper, registers a route for that container, and obtains an XPC endpoint viaRuntimeClient.createEndpoint. -
Bootstrap container – Using the endpoint, the apiserver sends a
bootstrapRPC to the runtime helper inSources/Services/RuntimeLinux/Server/RuntimeService.swift. The helper creates the VM, attaches the network interface, mounts image layers, and returns a ready state. -
Run processes – Subsequent commands such as
container execare forwarded over the same XPC connection to the runtime helper.
Code Examples
The following Swift snippets demonstrate the client-side interaction with the apiserver's XPC coordination:
// Start the API server (simplified)
let server = XPCServer(
identifier: "com.apple.container.apiserver",
routes: routes,
log: log
)
try await server.listen() // launches XPC helpers as plugins
// Pull an image (client-side)
let imageClient = ImageClient()
try await imageClient.pull(named: "ubuntu:latest") // talks to container-core-images
// Create a container (client-side)
let containerClient = ContainerClient()
let containerID = try await containerClient.create(
image: "ubuntu:latest",
network: "default"
) // apiserver contacts network & runtime helpers
// Start a process inside the container
try await containerClient.startProcess(
containerID: containerID,
command: ["/bin/bash"]
) // forwarded to container-runtime-linux via XPC
Summary
- The
container-apiserverinSources/APIServer/APIServer+Start.swiftcreates an XPC server with identifiercom.apple.container.apiserverto route client requests. - Image operations are delegated to
container-core-imagesvia theImagesHelper.swiftplugin, handling OCI registry interactions. - Network configuration is managed by
container-network-vmnetthrough theNetworkHelper.swiftplugin, providing VM-backed networking viavmnet. - Container execution is isolated to per-container instances of
container-runtime-linux, coordinated throughRuntimeClient.swiftandRuntimeService.swift. - All inter-process communication uses the ContainerXPC framework, ensuring type-safe RPCs between the apiserver and its helpers.
Frequently Asked Questions
What XPC service identifier does container-apiserver register?
The apiserver registers the XPC service com.apple.container.apiserver when starting via container system start. This identifier is defined in Sources/APIServer/APIServer+Start.swift and serves as the primary endpoint for all container-related client requests.
How does the apiserver isolate image operations from runtime execution?
The apiserver enforces isolation by loading separate binary helpers as plugins. Image operations run in container-core-images, while runtime execution occurs in container-runtime-linux. Each helper operates as an independent XPC service with distinct entitlements and process boundaries, preventing a crash in image parsing from affecting running containers.
Why is container-runtime-linux spawned per container?
The container-runtime-linux helper is spawned as a separate process for each container to provide strong isolation and lifecycle management. According to the implementation in Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift, the apiserver creates a unique XPC endpoint for each runtime instance, caching the connection for the container's lifetime. This design allows the apiserver to terminate or restart individual containers without affecting the system-wide container stack.
What framework mediates communication between the apiserver and helpers?
All XPC communication is mediated by the ContainerXPC framework imported throughout the codebase. This framework provides the underlying transport for RPCs between the apiserver and the image, network, and runtime helpers, ensuring type-safe message passing and proper handling of XPC endpoints.
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 →