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
MachineConfigstruct and stored in JSON files byContainerSystemConfig.swiftfor 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 machinesubcommands including create, run, set, and inspect. - Advanced features include nested virtualization support on M3+ hardware via
validateKernelPathand 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →