# How Container Uses XPC Services: container-apiserver and container-network-vmnet Explained

> Discover how Apple's container framework uses XPC services like container-apiserver and container-network-vmnet. Understand their roles in container lifecycle management and network allocation.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: internals
- Published: 2026-07-07

---

**Apple's Container framework uses XPC (Cross-Process Communication) to isolate the CLI, API server, and network helper, with `container-apiserver` managing container lifecycle and `container-network-vmnet` handling virtual network allocation through Mach service endpoints.**

The `apple/container` repository implements a secure, multi-process architecture where XPC services provide the backbone for container management on macOS. Understanding how `container-apiserver` and `container-network-vmnet` collaborate via Mach services reveals the design patterns behind this production-grade container runtime.

## Architecture Overview

### The API Server Launch Agent (container-apiserver)

The **`container-apiserver`** acts as the central launch agent that implements the container management API. According to the source code in [`Sources/APIServer/APIServer.swift`](https://github.com/apple/container/blob/main/Sources/APIServer/APIServer.swift) (lines 20-27), this executable defines the launch agent entry point using `ArgumentParser` scaffolding and registers sub-commands such as `Start`. The API server handles operations including container creation, image management, and lifecycle controls, exposing its functionality through the Mach service **`com.apple.container.apiserver`**.

### The Network Helper Plug-in (container-network-vmnet)

The **`container-network-vmnet`** service operates as an XPC plug-in that owns the virtual network (`vmnet`) subsystem. Implemented in [`Sources/Plugins/NetworkVmnet/NetworkVmnetHelper.swift`](https://github.com/apple/container/blob/main/Sources/Plugins/NetworkVmnet/NetworkVmnetHelper.swift) (lines 17-30), this helper is not a standalone persistent process but rather a specialized plug-in selected by the API server. It allocates IP addresses for containers and configures subnets by interfacing directly with the macOS `vmnet` framework. The helper shares the same Mach service endpoint as the API server, with the server routing network-specific requests to this component as needed.

## XPC Implementation Details

### Low-Level XPC Client (XPCClient.swift)

At the transport layer, [`Sources/ContainerXPC/XPCClient.swift`](https://github.com/apple/container/blob/main/Sources/ContainerXPC/XPCClient.swift) (lines 21-38) provides the foundational XPC communication wrapper. This implementation utilizes `xpc_connection_create_mach_service` to establish the Mach connection and exposes a `send(_:responseTimeout:)` method that delivers an `XPCMessage` and awaits typed replies. The client handles connection lifecycle management, timeout enforcement, and low-level error translation, throwing on communication failures or missed deadlines.

### High-Level Network Client (NetworkClient.swift)

Building atop the low-level transport, [`Sources/Services/ContainerAPIService/Client/NetworkClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/NetworkClient.swift) (lines 24-66) serves as the public Swift façade for network operations. This client constructs `XPCMessage` instances, transmits them via `XPCClient`, and decodes responses into Swift structs such as `NetworkResource` and `NetworkConfiguration`. It references `NetworkClient.defaultServiceIdentifier` to target the Mach service `com.apple.container.apiserver`, providing downstream developers with type-safe methods for network creation, listing, and deletion.

## Lifecycle and Communication Flow

The interaction between Container XPC services follows a strict initialization sequence:

1. **System Initialization**: The user executes `container system start`, which activates the `container-apiserver` launch agent as defined in [`Sources/APIServer/APIServer.swift`](https://github.com/apple/container/blob/main/Sources/APIServer/APIServer.swift).

2. **Helper Spawning**: When the first network operation is requested (such as creating a container with network access), `container-apiserver` automatically spawns the `container-network-vmnet` XPC helper.

3. **Client Connection**: Application code or the CLI instantiates a `NetworkClient`, which internally creates an `XPCClient` pointing at the Mach service `com.apple.container.apiserver`.

4. **Request Routing**: Method calls such as `create`, `list`, or `delete` are encoded into `XPCMessage` objects and sent over the XPC connection. The API server receives these messages and forwards network-specific requests to the `container-network-vmnet` plug-in.

5. **Response Handling**: The helper communicates with the `vmnet` framework to allocate IPs and configure interfaces, then returns results through the same XPC channel. `NetworkClient` unmarshals these replies into typed Swift structs for consumption by the caller.

## Practical Code Examples

### Managing Networks with NetworkClient

The high-level Swift API provides the recommended interface for network management:

```swift
import ContainerResource
import ContainerXPC
import Foundation

// Create a client that talks to the default API server.
let client = NetworkClient()

// 1️⃣ Create a new network
let config = NetworkConfiguration(
    id: "my-net",
    subnet: "192.168.65.0/24",
    gateway: "192.168.65.1"
)
let network = try await client.create(configuration: config)
print("Created network: \(network.id) – IP range \(network.subnet)")

// 2️⃣ List all networks
let networks = try await client.list()
print("All networks:")
for n in networks {
    print("- \(n.id) (builtin: \(n.isBuiltin))")
}

// 3️⃣ Delete a network (fails for the built-in default network)
try await client.delete(id: network.id)
print("Deleted network \(network.id)")

```

*Key files:* `NetworkClient` ([`Sources/Services/ContainerAPIService/Client/NetworkClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/NetworkClient.swift)) provides the entry point for XPC communication, while `XPCClient` ([`Sources/ContainerXPC/XPCClient.swift`](https://github.com/apple/container/blob/main/Sources/ContainerXPC/XPCClient.swift)) manages the underlying transport.

### Direct XPC Communication

For scenarios requiring low-level protocol access, use `XPCClient` directly:

```swift
import ContainerXPC

// Low-level client – you normally use NetworkClient instead.
let xpc = XPCClient(service: "com.apple.container.apiserver")

// Build a raw XPCMessage that asks the server to list networks.
var request = XPCMessage(route: .networkList)

// Send and wait for a reply (1-second timeout for demo purposes).
let reply = try await xpc.send(request, responseTimeout: .seconds(1))

// Extract the binary payload; decode as JSON array of NetworkResource.
if let data = reply.dataNoCopy(key: .networkResources) {
    let networks = try JSONDecoder().decode([NetworkResource].self, from: data)
    print("Found \(networks.count) networks")
}

```

This example illustrates how the library constructs the Mach connection and marshals messages as implemented in the `XPCMessage` protocol definitions.

### Starting the Container Subsystem

From the command line, initialize the XPC services:

```bash

# Start the container system (launches container-apiserver and its helpers)

$ container system start

# Verify the API server is running (process name appears in ps)

$ ps -ax | grep container-apiserver

```

The CLI internally instantiates an `XPCClient` targeting the Mach service, making subsequent commands such as `container run` or `container network create` thin wrappers around the XPC calls demonstrated above.

## Summary

- **Container XPC services** achieve process isolation by separating the CLI, API server (`container-apiserver`), and network helper (`container-network-vmnet`) into distinct components communicating via Mach services.
- **`container-apiserver`** functions as the launch agent implementing the container management API, while **`container-network-vmnet`** operates as a plug-in handling virtual network allocation.
- The **XPC transport layer** in [`Sources/ContainerXPC/XPCClient.swift`](https://github.com/apple/container/blob/main/Sources/ContainerXPC/XPCClient.swift) manages Mach connections and message delivery, while **NetworkClient** provides the type-safe Swift interface.
- Both services share the Mach service identifier **`com.apple.container.apiserver`**, with the API server routing network requests to the helper as documented in [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md) (lines 43-48).

## Frequently Asked Questions

### How does container-apiserver communicate with container-network-vmnet?

The API server spawns the network helper as an XPC plug-in when the first network operation is requested, forwarding specific requests to it while both utilize the same Mach service endpoint `com.apple.container.apiserver`. This architecture allows the network helper to run only when needed while maintaining a unified client interface.

### What Mach service identifier does Container use for XPC connections?

The framework uses **`com.apple.container.apiserver`** as the primary Mach service identifier, which is defined in `NetworkClient.defaultServiceIdentifier` and passed to `XPCClient` to establish the Mach connection via `xpc_connection_create_mach_service`.

### How do I start the Container XPC services and verify they are running?

Execute `container system start` to launch the `container-apiserver` launch agent; the network helper starts automatically when the first network request is made. Verify the API server is active by running `ps -ax | grep container-apiserver` or checking for the `com.apple.container.apiserver` Mach service registration.

### What is the difference between XPCClient and NetworkClient?

**`XPCClient`** ([`Sources/ContainerXPC/XPCClient.swift`](https://github.com/apple/container/blob/main/Sources/ContainerXPC/XPCClient.swift)) provides the low-level XPC transport handling connection creation, message sending, and timeout management, while **`NetworkClient`** ([`Sources/Services/ContainerAPIService/Client/NetworkClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/NetworkClient.swift)) offers the high-level Swift API that encodes method calls into `XPCMessage` objects and decodes responses into typed structs like `NetworkResource`.