# How to Start the Apple Container System Service on macOS

> Start the Apple Container system service on macOS with the container system start command. Learn how to register the API server and ensure it's responsive.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-07-05

---

**To start the Apple Container system service, run `container system start`, which registers the `container-apiserver` launchd agent with macOS launchd and performs health checks to ensure the API server is responsive.**

The Apple Container project provides a lightweight virtualization stack for macOS. Starting the system service initializes the `container-apiserver` daemon through launchd, enabling container operations across the platform. This guide explains the exact mechanism implemented in the `apple/container` repository, from configuration loading to service registration.

## Configuration Loading

Before registering the service, the CLI loads system configuration from [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift). According to the source in [`Sources/ContainerCommands/System/SystemStart.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/System/SystemStart.swift) (lines 82-86), the command reads `app-root` and `install-root` values to determine the init image (`vminit`) location and default kernel settings.

The configuration persists across reboots and defines where the service stores its plist, logs, and runtime data. If you run in a custom environment or CI pipeline, you can override these paths using command-line flags.

## Launchd Registration Process

The `container system start` command orchestrates service registration through several discrete steps implemented in [`Sources/ContainerCommands/System/SystemStart.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/System/SystemStart.swift).

### Binary Resolution and Plist Creation

First, the command resolves the real path of the `container-apiserver` binary (lines 93-96), dereferencing symlinks to ensure code signature validation succeeds. It then constructs a `LaunchPlist` struct (lines 15-22) with:

- **Label**: `com.apple.container.apiserver`
- **Program path**: The resolved binary path
- **Environment variables**: `APP_ROOT`, `INSTALL_ROOT`, and optional `LOG_ROOT`
- **Mach service entry**: For XPC communication with other components

### Service Registration

The `ServiceManager.register(plistPath:)` method in [`Sources/ContainerPlugin/ServiceManager.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPlugin/ServiceManager.swift) writes the plist to `$APP_ROOT/apiserver/plist` and executes `/bin/launchctl` to register the service with launchd (lines 29-31). This registration makes the service survive reboots and discoverable by the networking plugin and runtime components.

## Health Verification

After launchd starts the daemon, the CLI performs two validation checks defined in [`SystemStart.swift`](https://github.com/apple/container/blob/main/SystemStart.swift):

1. **API Server Health Check** (lines 33-40): Pings the `container-apiserver` to confirm responsiveness. If the check fails, the command aborts with a descriptive error before returning control to the user.
2. **Machine API Verification** (lines 44-48): Validates reachability of the machine-API server, ensuring the virtualization layer is fully operational.

## Optional Initialization Steps

Depending on your environment, `container system start` may perform additional setup:

### Init Image Handling

If the `vminit` init image is missing from the configured app-root, the command automatically pulls it using `container image pull` logic (lines 53-55). The fallback mechanism references [`scripts/install-init.sh`](https://github.com/apple/container/blob/main/scripts/install-init.sh) to build and load the image after a temporary stop/start cycle.

### Kernel Installation

Unless disabled with `--disable-kernel-install`, the command checks for the recommended kernel and may prompt for download via `KernelSet.downloadAndInstallWithProgressBar` (lines 74-95). Use `--enable-kernel-install` to force installation without interactive prompts.

## Command Examples

Run the service using the `container` CLI with various options:

```bash

# Basic start - registers launchd service and launches apiserver

container system start

```

```bash

# Custom roots for CI or isolated environments

container system start --app-root /tmp/container-app \
                       --install-root /opt/container-install \
                       --log-root /var/log/container

```

```bash

# Force kernel installation without prompts

container system start --enable-kernel-install

```

```bash

# Debug mode with verbose logging

container system start --debug

```

## Verification and Troubleshooting

After execution, verify the service status using standard macOS tools:

```bash

# Check if the service is loaded in launchd

sudo launchctl list com.apple.container.apiserver

```

If the command fails during the health-check phase, review logs in the configured `LOG_ROOT` directory. Common failures include code signature validation errors (when binary paths contain unresolved symlinks) or missing init images that failed to download automatically.

## Summary

- **`container system start`** is the primary command to start the Apple Container system service, implemented in [`Sources/ContainerCommands/System/SystemStart.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/System/SystemStart.swift).
- The command creates a launchd plist with label `com.apple.container.apiserver` and registers it via `ServiceManager.register(plistPath:)` in [`Sources/ContainerPlugin/ServiceManager.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPlugin/ServiceManager.swift).
- Health checks verify API server responsiveness and machine-API reachability before the command exits successfully.
- Configuration is loaded from [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift), determining paths for the init image (`vminit`) and default kernel.
- Optional flags control kernel installation (`--enable-kernel-install`, `--disable-kernel-install`) and debug logging.

## Frequently Asked Questions

### What is the `container-apiserver` launchd agent?

The `container-apiserver` is the system daemon managed by launchd that handles container operations in the Apple Container stack. When you run `container system start`, the CLI registers this agent with label `com.apple.container.apiserver`, making it persistent across reboots and available for XPC communication with other system components.

### Why does the command check for symlinked binary paths?

The `SystemStart` implementation resolves symlinks when locating the `container-apiserver` binary (lines 93-96) to ensure macOS code signature validation succeeds. Launchd requires the actual binary path for proper entitlements checking, so dereferencing symlinks prevents signature validation failures during service registration.

### How do I start the service without installing the kernel?

Use the `--disable-kernel-install` flag to skip kernel checks and installation prompts. This is useful in CI environments or when managing kernel versions separately: `container system start --disable-kernel-install`.

### Where is the launchd plist stored?

The plist is written to `$APP_ROOT/apiserver/plist` as implemented in [`ServiceManager.swift`](https://github.com/apple/container/blob/main/ServiceManager.swift). By default, this resides within your configured application root directory, but you can customize the location using the `--app-root` parameter when starting the service.