# How Health Check and Process Monitoring Work in apple/container

> Explore how apple/container uses HTTP health checks and configurable timeouts for process monitoring. Learn about the health endpoint and CLI ping function for reliable operation.

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

---

**The apple/container daemon exposes an HTTP `/health` endpoint via the container-apiserver, while the CLI uses `ClientHealthCheck.ping(timeout:)` with configurable timeouts to verify liveness before executing commands.**

The apple/container repository provides a macOS container runtime that relies on a background daemon for orchestration. To ensure reliability, the project implements a two-layer **health check and process monitoring** strategy that combines HTTP-based liveness probes with launchd process supervision. This architecture allows the CLI to detect daemon state instantly and recover from failures without hanging the user terminal.

## Health Check Request Flow

### The HTTP Endpoint and HealthCheckService

In `Sources/APIServer/APIServer+Start.swift` (lines 248-260), the apiserver initializes a **HealthCheckService** that registers the `/health` route during startup. This service gathers runtime metadata and returns a JSON payload containing version information and filesystem paths.

### Client Implementation with Timeouts

The `ClientHealthCheck.ping(timeout:)` method in [`Sources/Services/ContainerAPIService/Client/ClientHealthCheck.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/ClientHealthCheck.swift) sends an HTTP `GET` request to `http://127.0.0.1:2379/health`. The implementation wraps all requests in configurable timeouts—`.seconds(2)` for status checks and `.seconds(10)` for version queries—preventing CLI hangs when the daemon is unresponsive.

### SystemHealth Data Structure

The JSON response decodes into the `SystemHealth` struct defined in [`Sources/Services/ContainerAPIService/Client/SystemHealth.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/SystemHealth.swift). This model includes:

- `appRoot`: Path to container-app data
- `installRoot`: Location of container binaries
- `logRoot`: Optional directory for log files
- `apiServerVersion`, `apiServerCommit`, `apiServerBuild`, `apiServerAppName`: Daemon versioning metadata

## Process Monitoring Architecture

### launchd Integration

The apiserver runs as a launchd job named `com.apple.container.apiserver`. The CLI commands `container system start`, `container system stop`, and `container system status` interface with launchd via `launchctl` to query job states and manage the service lifecycle. This provides OS-level automatic restart capabilities if the daemon crashes.

### Failure Detection and Recovery

When the health check fails or times out, the CLI treats the daemon as dead and skips further actions. For example, `container system stop` prints "APIServer health check failed, skipping bootout" when it cannot reach the endpoint, preventing destructive operations against an already-stopped service.

### Log-Based Monitoring

The `--log-root` option enables file-based logging, allowing the CLI to stream real-time diagnostics via `container system logs`. The apiserver writes logs to the specified directory while the CLI reads these files to provide continuous monitoring capabilities.

## Practical Implementation Examples

### Checking Daemon Health in Swift

```swift
import ContainerAPIService

// Ping the apiserver with a 2-second timeout
do {
    let health = try await ClientHealthCheck.ping(timeout: .seconds(2))
    print("Daemon version:", health.apiServerVersion)
    print("App root:", health.appRoot.path)
} catch {
    print("Health check failed:", error)
}

```

### CLI Status Commands

When the daemon is running:

```bash
$ container system status
┌─────────────────────┬───────────┐
│ COMPONENT           │ STATUS    │
├─────────────────────┼───────────┤
│ container-apiserver │ running   │
└─────────────────────┴───────────┘

```

When the daemon is down:

```bash
$ container system status
⚠️  APIServer health check failed, skipping bootout

```

## Summary

- The **health check and process monitoring** system uses a two-layer approach: HTTP `/health` endpoints for fast liveness checks and launchd for OS-level process supervision.
- `ClientHealthCheck.ping(timeout:)` in [`ClientHealthCheck.swift`](https://github.com/apple/container/blob/main/ClientHealthCheck.swift) implements timeout-protected HTTP requests to prevent CLI hangs.
- The `SystemHealth` struct in [`SystemHealth.swift`](https://github.com/apple/container/blob/main/SystemHealth.swift) provides structured metadata including paths, versions, and build information.
- **launchd integration** via `com.apple.container.apiserver` ensures automatic recovery and provides standard start/stop semantics.
- Configurable timeouts (2 seconds for status, 10 seconds for version) balance responsiveness against network variability.

## Frequently Asked Questions

### How does the apple/container CLI detect if the daemon is running?

The CLI calls `ClientHealthCheck.ping(timeout:)` which sends an HTTP `GET` request to `http://127.0.0.1:2379/health`. If the request succeeds within the timeout window (2 seconds for status commands), the daemon is considered alive; otherwise, the CLI reports it as unavailable and skips dependent operations.

### What information does the health check endpoint return?

The `/health` endpoint returns a JSON payload that decodes into the `SystemHealth` struct, containing `appRoot`, `installRoot`, `logRoot` paths, and versioning metadata including `apiServerVersion`, `apiServerCommit`, and `apiServerBuild`.

### What happens if the health check times out?

If the health check exceeds its configured timeout—`.seconds(2)` for status checks or `.seconds(10)` for version queries—the CLI assumes the daemon is unhealthy. Commands like `container system stop` will print a warning and skip bootout operations to avoid hanging the terminal or executing invalid state transitions.

### How is the container-apiserver process monitored at the OS level?

The apiserver registers as a launchd job named `com.apple.container.apiserver`. This provides macOS-level process supervision, ensuring the daemon restarts automatically after crashes and integrates with the system's service management framework for reliable start/stop operations.