# How to Create and Manage Container Machines with Apple Container

> Learn to create and manage container machines with Apple Container using its Swift-based Machine API Service and `container machine` CLI for persistent Linux environments.

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

---

**Apple Container treats container machines as persistent Linux environments managed through a Swift-based Machine API Service, allowing you to create, run, configure, and delete VMs using the `container machine` CLI commands.**

Apple Container provides a native macOS solution for running persistent Linux environments known as container machines. Unlike ephemeral containers, these machines maintain a root filesystem on disk and run an init system, mapping your host macOS user into the virtual machine. According to the apple/container repository, the architecture relies on a Machine API Service that tracks state and exposes a JSON-over-HTTP interface, while the `container machine` CLI commands handle the full lifecycle from creation to deletion.

## Architecture of Container Machines

### Machine API Service

The **Machine API Service** is a Swift-based server that tracks container-machine state, stores configuration artifacts, and exposes a JSON-over-HTTP API. In [`Sources/Services/MachineAPIService/Server/MachinesService.swift`](https://github.com/apple/container/blob/main/Sources/Services/MachineAPIService/Server/MachinesService.swift), the service handles create, delete, list, inspect, and configuration update operations. This service validates that images contain `/sbin/init` before creating a machine, generates unique IDs, and writes `MachineConfig` artifacts to disk via [`Sources/ContainerPersistence/MachineConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift).

### Machine Client

The **Machine Client** acts as a thin Swift wrapper that communicates with the API. Defined in [`Sources/Services/MachineAPIService/Client/MachineClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/MachineAPIService/Client/MachineClient.swift), this client serializes requests, parses responses, and surfaces errors to the CLI. All user-facing commands delegate to this client, ensuring consistent error handling and request formatting.

### Container Commands

The `container machine` subcommands parse arguments, resolve target machines (default or explicit via `-n`), and invoke the client. Key implementations include:

- [`MachineCreate.swift`](https://github.com/apple/container/blob/main/MachineCreate.swift) – Handles creation logic and `--set-default` flag processing
- [`MachineRun.swift`](https://github.com/apple/container/blob/main/MachineRun.swift) – Manages booting stopped machines and executing shells or binaries
- [`MachineSet.swift`](https://github.com/apple/container/blob/main/MachineSet.swift) – Modifies persistent configuration resources
- [`MachineStop.swift`](https://github.com/apple/container/blob/main/MachineStop.swift) – Gracefully shuts down VMs and clears container IDs
- [`MachineDelete.swift`](https://github.com/apple/container/blob/main/MachineDelete.swift) – Removes configurations, root filesystems, and OCI bundles
- [`MachineList.swift`](https://github.com/apple/container/blob/main/MachineList.swift) and [`MachineInspect.swift`](https://github.com/apple/container/blob/main/MachineInspect.swift) – Query state and metadata

All commands share logic in [`Sources/ContainerCommands/Machine/MachineHelpers.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Machine/MachineHelpers.swift) to resolve IDs, check default presence, and format error messages.

## Creating a Container Machine

Creating a machine requires an image with `/sbin/init`. The service validates this requirement, generates a unique ID, and writes a `MachineConfig` specifying boot-time resources (CPUs, memory, home-mount) to disk. If you pass `--set-default`, the new ID is stored in the user defaults file for subsequent commands.

```bash

# Create a machine from Alpine and set it as default

container machine create --name dev --set-default alpine:3.22

# List machines to verify creation (default is marked)

container machine ls

```

## Running and Managing Container Machines

### Starting and Running Commands

The `container machine run` command first resolves the target machine using the default or the `-n` flag. If the machine is stopped, [`MachinesService.swift`](https://github.com/apple/container/blob/main/MachinesService.swift) boots it via the container runtime. The command either opens an interactive login shell as the host user or executes the supplied binary inside the VM.

```bash

# Interactive shell in default machine

container machine run

# Execute command in named machine

container machine run -n dev uname -a

```

### Configuring Resources

Use `container machine set` to mutate `MachineConfig` on disk. Changes only apply after the next stop/start cycle, guaranteeing consistency. For example, to allocate 4 CPUs and 8GB of memory:

```bash
container machine set -n dev cpus=4 memory=8G

```

You must stop the machine before the changes take effect.

### Stopping and Deleting

Stop gracefully shuts down the VM and clears the container ID, while delete removes the configuration, persistent root filesystem, and associated OCI bundles.

```bash

# Stop the machine

container machine stop dev

# Verify auto-boot on next run

container machine run -n dev -- cat /proc/cpuinfo

# Remove permanently

container machine rm dev

```

## Programmatic Management with Swift

You can manage machines programmatically using the `MachineClient` Swift API. This is useful for building automation tools or integrating with macOS applications.

```swift
import MachineAPIService

let client = MachineClient()
let config = MachineConfiguration(
    id: "dev",
    image: "alpine:3.22",
    platform: .linux,
    resources: MachineResources(cpus: 2, memory: "4G")
)

try await client.createMachine(configuration: config, setDefault: true)

```

To inspect a machine's state and storage location:

```swift
let snapshot = try await client.inspectMachine(id: "dev")
print("Status:", snapshot.state)               // e.g. "running"
print("Rootfs path:", snapshot.rootfsPath)     // persistent location on disk

```

## Summary

- Container machines are persistent Linux environments running an init system with macOS user mapping, managed through the Machine API Service in [`MachinesService.swift`](https://github.com/apple/container/blob/main/MachinesService.swift)
- The CLI delegates to [`MachineClient.swift`](https://github.com/apple/container/blob/main/MachineClient.swift), with command implementations in `Sources/ContainerCommands/Machine/` including [`MachineCreate.swift`](https://github.com/apple/container/blob/main/MachineCreate.swift), [`MachineRun.swift`](https://github.com/apple/container/blob/main/MachineRun.swift), and [`MachineDelete.swift`](https://github.com/apple/container/blob/main/MachineDelete.swift)
- Creation validates `/sbin/init`, generates a unique ID, and persists configuration via [`MachineConfig.swift`](https://github.com/apple/container/blob/main/MachineConfig.swift)
- The `container machine run` command auto-boots stopped machines and supports both interactive shells and binary execution
- Configuration changes via `container machine set` apply only after the next stop/start cycle
- Swift developers can use `MachineClient` to programmatically create, inspect, and manage machines

## Frequently Asked Questions

### What is the difference between a container and a container machine in Apple Container?

A container machine is a persistent Linux environment that runs an init system and maintains its root filesystem on disk between restarts, whereas standard containers are typically ephemeral. According to the source code in [`MachinesService.swift`](https://github.com/apple/container/blob/main/MachinesService.swift), machines specifically require an image containing `/sbin/init` and map the host macOS user into the VM.

### How do I change the CPU and memory allocation for an existing container machine?

Use `container machine set -n <name> cpus=<value> memory=<value>` to update the `MachineConfig` stored on disk. As implemented in [`MachineSet.swift`](https://github.com/apple/container/blob/main/MachineSet.swift), these changes only take effect after you stop and restart the machine, ensuring configuration consistency.

### Can I use Apple Container machines for development environments like VS Code?

Yes. The repository includes a complete example in [`examples/container-machine-vscode/README.md`](https://github.com/apple/container/blob/main/examples/container-machine-vscode/README.md) demonstrating how to configure a container machine as a remote development environment. You can SSH into the machine or use the `container machine run` command to execute development tools.

### Where does Apple Container store machine configuration and persistent data?

Machine configurations are persisted via [`Sources/ContainerPersistence/MachineConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift), which stores boot-time resources and the unique machine ID. The root filesystem and associated OCI bundles are stored on disk at paths exposed through the `inspect` command's `rootfsPath` property.