Apple Container Runtime APIs: Complete Swift Client Reference
Apple's container runtime exposes 15 public asynchronous methods through the ContainerClient class in ContainerClient.swift, enabling container lifecycle management, process execution, and resource monitoring via XPC.
The apple/container repository provides a native Swift implementation of container runtime functionality designed for macOS. Developers interact with this system through the Apple container runtime APIs, a type-safe Swift interface that maps public methods to XPC routes while handling JSON encoding, request routing, and error translation automatically.
ContainerClient: The Swift API Entry Point
All public API interaction flows through the ContainerClient class defined in Sources/Services/ContainerAPIService/Client/ContainerClient.swift. This client acts as a thin Swift wrapper that communicates with the container API server over XPC. Each method corresponds to a specific XPC route (such as .containerCreate or .containerList) and utilizes the private xpcSend(message:timeout:) helper to manage request forwarding, timeout handling, and error conversion to ContainerizationError.
All methods are declared as async throws, requiring Swift concurrency patterns for invocation.
Core Container Lifecycle APIs
Creating and Configuring Containers
The create(configuration:options:kernel:initImage:runtimeData:) method initializes new containers from a ContainerConfiguration object and a Kernel description. This method accepts optional creation parameters via ContainerCreateOptions, allowing developers to specify resource limits, environment variables, and initialization images before the container enters the created state.
Listing and Inspecting Containers
To retrieve container state, use list(filters:), which returns an array of ContainerSnapshot objects matching the supplied ContainerListFilters. For single-container lookups, the get(id:) convenience method returns a specific ContainerSnapshot for the provided container identifier.
Stopping and Deleting Containers
Graceful shutdown is handled by stop(id:opts:), which accepts ContainerStopOptions to configure timeout intervals and termination signals. For immediate termination, kill(id:signal:) sends POSIX signals (such as "SIGTERM" or "SIGKILL") directly to the container's main process. Finally, delete(id:force:) removes the container and its resources; setting force to true ensures deletion even when the container is running.
Process Execution and Management
Bootstrapping the Init Process
The bootstrap(id:stdio:dynamicEnv:) method starts the init process of a container and returns a ClientProcess handle (implemented by ClientProcessImpl in Sources/ContainerAPIService/Client/ClientProcess.swift). This handle enables interaction with the process stdin, stdout, and stderr through provided FileHandle arrays.
Creating Additional Processes
For running multiple processes within an existing container, createProcess(containerId:processId:configuration:stdio:) creates new processes in the created state. This method requires a ProcessConfiguration object and returns a ClientProcess handle for process interaction.
File System and Networking Operations
Copying Files Between Host and Container
The API provides bidirectional file system operations:
copyIn(id:source:destination:mode:createParents:)transfers files or directories from the host into the container filesystem.copyOut(id:source:destination:createParents:)retrieves files from the container back to the host.
Both methods support optional parent directory creation and permission mode specification for copyIn.
Accessing Logs and Network Ports
To retrieve container output, logs(id:) returns a set of FileHandle objects representing stdout and stderr streams. For network connectivity, dial(id:port:) opens a vSock connection to a container-exposed port and returns a single FileHandle for communication.
Monitoring and Resource APIs
Runtime Statistics
The stats(id:) method retrieves live performance data via ContainerStats (defined in Sources/ContainerResource/Container/ContainerStats.swift), exposing CPU usage, memory consumption, and I/O metrics as structured data.
Disk Usage and Export
For storage management, diskUsage(id:) queries the size of a container's writable layer, returning a UInt64 byte count. To archive containers, export(id:archive:) exports the container filesystem to a tar archive at the specified URL.
Practical Usage Examples
The following examples demonstrate common API patterns using ContainerClient:
import ContainerAPI
// Initialize the client
let client = ContainerClient()
// Create a container with default kernel
let cfg = ContainerConfiguration(name: "my-app", image: .init(name: "my-image"))
try await client.create(configuration: cfg, kernel: .default, runtimeData: nil)
// List all containers
let containers = try await client.list()
print("Running containers:", containers.map { $0.id })
// Bootstrap init process with attached stdio
let proc = try await client.bootstrap(
id: containers[0].id,
stdio: [FileHandle.standardInput, FileHandle.standardOutput, FileHandle.standardError]
)
// Send SIGTERM to container
try await client.kill(id: containers[0].id, signal: "SIGTERM")
// Retrieve resource statistics
let stats = try await client.stats(id: containers[0].id)
print("CPU:", stats.cpuUsage, "Memory:", stats.memoryUsage)
// Export to tar archive
let archiveURL = URL(fileURLWithPath: "/tmp/my-container.tar")
try await client.export(id: containers[0].id, archive: archiveURL)
Summary
- Apple container runtime APIs are exposed through the
ContainerClientclass inSources/Services/ContainerAPIService/Client/ContainerClient.swift. - All 15 public methods are asynchronous (
async throws) and communicate via XPC usingxpcSend(message:timeout:). - APIs cover the full container lifecycle: create, list, get, bootstrap, kill, stop, and delete.
- Process management supports both init bootstrapping and additional process creation with
ClientProcesshandles. - File system operations include bidirectional copy, log retrieval, and vSock networking via
dial. - Monitoring capabilities include runtime statistics (
ContainerStats) and disk usage queries.
Frequently Asked Questions
What is the ContainerClient in Apple's container runtime?
The ContainerClient is the primary Swift interface to the Apple container runtime APIs, defined in Sources/Services/ContainerAPIService/Client/ContainerClient.swift. It wraps XPC communication and provides 15 type-safe asynchronous methods for container management, translating requests to XPC routes and converting errors to ContainerizationError types.
How does the Apple container runtime communicate between client and server?
The runtime uses XPC (Inter-Process Communication) for all client-server communication. The ContainerClient serializes requests into XPCMessage objects (defined in Sources/ContainerXPC/XPCMessage.swift) and forwards them via the private xpcSend(message:timeout:) method to the container API server, handling JSON encoding and response parsing automatically.
What types of operations can I perform with the container runtime APIs?
The APIs support four major categories: lifecycle management (create, stop, delete), process execution (bootstrap, createProcess, kill), file system operations (copyIn, copyOut, logs, dial), and resource monitoring (stats, diskUsage, export). All operations are available as async throws methods on the ContainerClient instance.
Are the Apple container runtime APIs synchronous or asynchronous?
All public APIs are asynchronous and utilize Swift concurrency. Every method in ContainerClient is declared as async throws, requiring try await syntax for invocation. This design accommodates XPC communication delays and I/O operations without blocking the calling thread.
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 →