container-apiserver: Orchestrating Container Lifecycles on macOS

container-apiserver is the central API server that exposes XPC-based services to create, start, stop, inspect, and delete containers, serving as the primary orchestrator for macOS container lifecycle management.

The container-apiserver is the backbone of Apple's open-source apple/container repository, running as a system-level launch daemon that bridges CLI commands with kernel-level container operations. This Swift-based service handles everything from sandbox allocation to network configuration, ensuring reliable container lifecycle management across macOS systems.

XPC Server Architecture and Route Registration

At the core of the container-apiserver is an XPC (Inter-Process Communication) server that exposes container lifecycle operations to clients. The server registers route handlers that map incoming XPC calls to specific service harnesses responsible for containers, networks, volumes, and health checks.

The binary entry point is defined in Sources/APIServer/APIServer.swift, where the main function declares the command name and version through a CommandConfiguration. When the server starts, it executes the start sub-command defined in Sources/APIServer/APIServer+Start.swift.

In APIServer+Start.swift, the XPCServer is instantiated with the Mach service identifier com.apple.container.apiserver and a dictionary of route handlers. These routes map specific XPC calls—such as containerCreate, containerStartProcess, containerStop, and containerDelete—to their corresponding harness implementations:

// Excerpt from Sources/APIServer/APIServer+Start.swift
routes[XPCRoute.containerCreate] = XPCServer.route(ContainersHarness.create)
routes[XPCRoute.containerStartProcess] = XPCServer.route(ContainersHarness.startProcess)
routes[XPCRoute.containerStop] = XPCServer.route(ContainersHarness.stop)
routes[XPCRoute.containerDelete] = XPCServer.route(ContainersHarness.delete)

Container Lifecycle Operations

The Sources/Services/ContainerAPIService/Server/Containers/ContainersHarness.swift file implements the concrete handlers for container lifecycle management. Each harness method delegates to underlying service implementations that interact with the macOS sandbox and kernel extensions.

When a client invokes container create, the server allocates a sandbox, mounts volumes, configures networking, and persists the configuration via ContainerPersistence components. The ContainersHarness coordinates these resources before returning the container ID to the caller.

Process execution flows through containerStartProcess, which manages the actual runtime inside the container, including I/O handling and CPU/memory accounting. Graceful teardown occurs via containerStop and containerDelete, which trigger resource cleanup, network de-registration, and persistent state removal.

System Integration and Health Monitoring

The container-apiserver integrates deeply with macOS system services through launch daemon registration. In Sources/ContainerCommands/System/SystemStart.swift, the server generates a launch-daemon plist (apiserver.plist) that registers the Mach service name com.apple.container.apiserver and configures the daemon to start automatically.

Health monitoring is implemented in Sources/Services/ContainerAPIService/Server/HealthCheck/HealthCheckHarness.swift. This harness populates health-check replies with metadata including apiServerVersion, apiServerAppName, and build information, which the container system status command surfaces to users:


# Query the server's health-check endpoint

$ container system status
apiserver.version   1.2.3
apiserver.commit    abcdef1
apiserver.build     2024-08-15
apiserver.appName   container-apiserver

Networking and Plugin System Initialization

Before accepting container operations, the server initializes a plugin system via initializePluginLoader, which discovers built-in and user-installed plugins. Plugins declaring shouldBoot = true are loaded immediately and can extend the API surface or provide custom resources, such as the container-network-vmnet plugin for NAT networking.

DNS resolution is handled by two specialized resolvers—one for container hostnames and one for localhost—started during server initialization in APIServer+Start.swift. These resolvers feed into the container-wide DNS stack, ensuring proper name resolution within isolated network namespaces.

Summary

  • container-apiserver runs as the launch daemon com.apple.container.apiserver and serves as the central API server for macOS container lifecycle management.
  • The XPC server in APIServer+Start.swift registers route handlers that map calls like containerCreate and containerStop to harnesses in ContainersHarness.swift.
  • System integration occurs through SystemStart.swift, which creates the launch-daemon plist and registers the Mach service for automatic startup.
  • Health monitoring via HealthCheckHarness.swift exposes version and build metadata through the container system status command.
  • Plugin support allows extending container capabilities, with built-in plugins providing networking features like NAT via container-network-vmnet.

Frequently Asked Questions

How does container-apiserver communicate with client CLI tools?

Client CLI tools communicate with container-apiserver via XPC (Inter-Process Communication) calls. The CLI acts as a thin wrapper that forwards commands like container create or container stop to the XPC server running as com.apple.container.apiserver, which then routes the requests to the appropriate service harnesses.

Where is the container state persisted across daemon restarts?

The server works with ContainerPersistence components to load and store container, network, and volume configurations on disk. This persistent state ensures that container definitions survive daemon restarts and system reboots, with data managed through the service harnesses in coordination with the API server.

What information does the health-check endpoint provide?

The HealthCheckHarness populates replies containing apiServerVersion, apiServerAppName, apiServerCommit, and build dates. This metadata is surfaced through the container system status command and allows clients to verify compatibility and deployment versions with the running daemon.

Can container-apiserver be started manually for debugging?

While normally started by launchd automatically, you can invoke the binary directly for debugging or development purposes using the start sub-command. The server will initialize the XPC listener, register all service routes, and begin accepting connections until terminated:


# Start the API server manually

$ container-apiserver start

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 →