What Are Container Machines in Apple's Container Runtime?

A container machine is a persistent Linux environment built from OCI images that runs an init system like systemd, shares your macOS home directory, and behaves like a lightweight VM integrated with Apple's container runtime.

Container machines in the apple/container repository represent a specialized abstraction that bridges ephemeral application containers and full virtual machines. Unlike standard containers designed for single-process isolation, these machines provide a complete, bootable Linux userspace with persistent storage and tight macOS integration. They enable developers to run long-running services, test process supervisors, and maintain a true Linux filesystem hierarchy while retaining native macOS file access.

Understanding Container Machine Architecture

OCI-Based Images with Init System Support

Container machines are constructed from standard OCI images that contain /sbin/init, allowing them to function as lightweight Linux distributions rather than isolated application bundles. According to docs/container-machine.md, the image must provide an init system because the container machine boots a full Linux environment capable of running persistent daemons and services.

Persistent Filesystem and Configuration

The filesystem created for a container machine survives restarts and is stored on disk, providing a "persistent VM" feel. Configuration parameters including CPU count, memory allocation, and home-mount settings are serialized to a JSON MachineConfig file. As implemented in Sources/ContainerPersistence/MachineConfig.swift, the MachineConfig struct encodes these settings and validates kernel paths through the validateKernelPath method when nested virtualization is enabled.

macOS Integration and User Space Sharing

Automatic Home Directory Mapping

When you create a container machine, the host username and $HOME directory are automatically mapped into the Linux environment. This creates a bidirectional share between /Users/<username> on macOS and /home/<user> in the container, making dotfiles, SSH keys, and repositories immediately available without file copying or manual volume mounting.

Resource Management via MachineConfig

Dynamic resource adjustments are handled through the MachineConfig structure persisted via Sources/ContainerPersistence/ContainerSystemConfig.swift. Changes to CPU, memory, or mount options are written to disk and applied on the next boot cycle, allowing you to resize machines without recreation.

CLI Lifecycle Management

Creating and Booting Machines

The container machine subcommand (aliased as m) drives the complete lifecycle. The implementation in Sources/ContainerCommands/Machine/MachineCreate.swift handles image resolution, kernel validation for virtualization support, and initial boot sequencing.

container machine create alpine:latest --name dev

Running Commands and Interactive Shells

The MachineRun.swift source file implements the container machine run command, which can execute single commands or spawn interactive login shells matching your macOS username. If the machine is stopped, the run command automatically boots it first.


# Run a single command

container machine run -n dev uname -a

# Open an interactive login shell

container machine run -n dev

You can also set a default machine to avoid specifying the -n flag repeatedly:

container machine set-default dev
container machine run            # operates on the default machine

Advanced Capabilities

Nested Virtualization Support

On Apple Silicon M3+ systems running macOS 15+, container machines can expose /dev/kvm to run nested VMs. The kernel path is validated by MachineConfig.validateKernelPath in MachineConfig.swift before boot.

container machine create \
    --virtualization \
    --kernel /path/to/vmlinux-kvm \
    --name kvm-dev \
    alpine:latest

Custom Image Requirements

Any Linux image containing /sbin/init can serve as a container machine base. Custom images typically install systemd, essential tools, and a create-user.sh script that executes on first boot to establish the user environment.


# Build custom image with systemd and init support

container build -t local/ubuntu-machine:latest .

# Create machine from custom image

container machine create local/ubuntu-machine:latest --name ubuntu

Resource adjustments can be applied dynamically using the set subcommand documented in docs/command-reference.md:

container machine set -n dev cpus=4 memory=8G home-mount=ro
container machine stop dev
container machine run -n dev nproc   # shows the new CPU count

Summary

  • Container machines provide persistent Linux environments with init systems, bridging the gap between containers and VMs in Apple's container runtime.
  • Configuration is managed through the MachineConfig struct and stored in JSON files by ContainerSystemConfig.swift for persistence across reboots.
  • Automatic user and home directory mapping creates seamless macOS integration without manual volume configuration.
  • The CLI supports full lifecycle management through container machine subcommands including create, run, set, and inspect.
  • Advanced features include nested virtualization support on M3+ hardware via validateKernelPath and compatibility with custom OCI images containing /sbin/init.

Frequently Asked Questions

What is the difference between a container machine and a regular container?

A regular container typically runs a single application process in an isolated environment, while a container machine boots a full Linux system with an init process like systemd. Container machines persist their filesystem across restarts and share your macOS home directory, functioning more like lightweight VMs than ephemeral application containers.

How does container machine persistence work?

The filesystem is stored on disk and survives reboots, while configuration changes are written to a MachineConfig JSON file as implemented in Sources/ContainerPersistence/MachineConfig.swift. Resources and settings are applied on the next boot, allowing you to modify CPU, memory, and mount options without recreating the machine.

Can I run Docker inside a container machine?

Yes, when running on Apple Silicon M3+ with macOS 15+, you can enable nested virtualization by providing a KVM-capable kernel via the --kernel flag. This exposes /dev/kvm inside the container machine, allowing you to run nested VMs or container runtimes that require hardware virtualization.

Where is the container machine configuration stored?

Configuration is persisted in a JSON MachineConfig file managed by Sources/ContainerPersistence/ContainerSystemConfig.swift. This file stores CPU counts, memory limits, home-mount settings, and kernel paths, encoding the MachineConfig struct defined in Sources/ContainerPersistence/MachineConfig.swift.

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 →