# How to Create a Container Machine with Apple's Container Runtime

> Learn to create a container machine using Apple's container runtime. Follow simple commands to launch a persistent Linux VM with auto-mounted macOS directories.

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

---

**To create a container machine with Apple's container runtime, run `container machine create <image>` followed by `container machine run -n <name>` to launch a persistent Linux VM with your macOS home directory automatically mounted.**

Apple's open-source `container` repository provides a native macOS tool for running persistent Linux VMs called **container machines**. Built from standard OCI images, these machines run via the built-in container runtime on Apple Silicon, automatically mapping your macOS `$HOME` directory into the VM for seamless cross-platform development. This guide walks through the complete workflow from image selection to advanced configuration using the `apple/container` source code.

## What is a Container Machine?

A **container machine** is a persistent Linux virtual machine that runs on macOS using the native `container` runtime. Unlike ephemeral containers, machines maintain state across restarts and provide a full init system (such as `systemd`) for running background services. According to the `apple/container` source code, the runtime stores machine configurations in `~/.container/machines` and automatically handles VM lifecycle management, including home directory sharing and resource allocation.

## Prerequisites

Before creating a container machine, ensure you have:

1. The `container` tool installed on macOS (Apple Silicon)
2. The system service running (`container system start`)
3. An OCI-compatible Linux image (any distro shipping `/sbin/init`)

## Creating Your First Container Machine

The workflow consists of three phases: selecting an image, creating the machine registration, and starting the VM.

### Step 1: Select an OCI Image

Choose a standard Linux distribution image from a registry or build a custom one. The image must include an init system (like `systemd` or OpenRC) to function as a persistent machine.

```bash

# Use a lightweight Alpine image for testing

container machine create alpine:latest --name dev

```

### Step 2: Create the Machine

The `container machine create` command registers the VM in `~/.container/machines` and persists the root filesystem. As implemented in [`Sources/ContainerPersistence/MachineConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift), this stores configuration details including CPU count, memory limits, and virtualization flags.

```bash

# Create with explicit resources

container machine create ubuntu:24.04 --name ubuntu-dev --virtualization

```

### Step 3: Start and Use the Machine

Run `container machine run` to start the VM (if stopped) and open an interactive shell. The runtime automatically mounts the host's `$HOME` at the same path inside the VM and launches a user session matching your macOS account.

```bash

# Open interactive shell

container machine run -n dev

# Execute a single command

container machine run -n dev uname -a

```

## Configuring Container Machine Resources

After creation, tune CPU and memory allocations using the `set` subcommand. Changes are persisted in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift) and apply after the next stop/start cycle.

```bash

# Set defaults to avoid typing -n flag

container machine set-default dev

# Adjust resources (takes effect after restart)

container machine set -n dev cpus=4 memory=8G
container machine stop dev
container machine run  # Starts with new resources

```

**Home-directory sharing** keeps your macOS files synchronized at `/Users/<username>` inside the VM, while **persistent state** ensures changes to the root filesystem survive machine restarts.

## Advanced: Custom Images and Nested Virtualization

### Building a Custom Image with systemd

For full Linux environment compatibility, build an image containing `systemd` and essential tools. The `examples/container-machine-vscode/Dockerfile` in the repository provides a reference implementation.

```dockerfile
FROM ubuntu:24.04
ENV container container
RUN apt-get update && \
    apt-get install -y dbus systemd openssh-server net-tools iproute2 iputils-ping curl wget vim-tiny man sudo && \
    apt-get clean && rm -rf /var/lib/apt/lists/* && \
    yes | unminimize

# Prepare machine-id files required by systemd

RUN >/etc/machine-id && >/var/lib/dbus/machine-id

# Systemd defaults

RUN systemctl set-default multi-user.target
RUN systemctl mask dev-hugepages.mount sys-fs-fuse-connections.mount \
    systemd-update-utmp.service systemd-tmpfiles-setup.service \
    console-getty.service
RUN systemctl disable networkd-dispatcher.service

```

Build and deploy the custom image:

```bash
container build -t local/ubuntu-machine:latest .
container machine create local/ubuntu-machine:latest --name ubuntu

```

### Enabling Nested Virtualization on Apple Silicon

On Apple Silicon M3+ running macOS 15+, enable KVM inside the machine by providing a kernel compiled with `CONFIG_KVM=y`.

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

# Verify KVM device is exposed

container machine run -n kvm-dev -- ls -l /dev/kvm

```

### Automating User Creation with First-Boot Scripts

Embed a script at [`/etc/machine/create-user.sh`](https://github.com/apple/container/blob/main//etc/machine/create-user.sh) inside your image to control first-boot user setup. The runtime executes this script with environment variables including `$CONTAINER_USER`.

```bash
#!/bin/bash

# /etc/machine/create-user.sh

useradd -m -s /bin/bash "$CONTAINER_USER"
echo "$CONTAINER_USER ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

```

## Understanding the Configuration Architecture

The `apple/container` runtime persists machine state using Swift structures defined in [`Sources/ContainerPersistence/MachineConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift), which handles on-disk configuration for CPU, memory, and home-mount settings. Global system settings and the persistent state for all machines are managed by [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift). For complete command syntax, refer to [`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md) and [`docs/container-machine.md`](https://github.com/apple/container/blob/main/docs/container-machine.md) in the repository.

## Summary

- **Container machines** are persistent Linux VMs running via Apple's native container runtime on macOS
- **Create** machines with `container machine create <image> --name <name>` and manage them via `container machine run`
- **Configuration** persists in `~/.container/machines` and includes CPU, memory, and virtualization flags
- **Home directory sharing** automatically mounts macOS `$HOME` inside the VM at the same path
- **Nested virtualization** requires Apple Silicon M3+ and a kernel with `CONFIG_KVM=y`
- **Custom images** need only an init system (`/sbin/init`) and optionally [`/etc/machine/create-user.sh`](https://github.com/apple/container/blob/main//etc/machine/create-user.sh) for user setup

## Frequently Asked Questions

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

A container machine is a persistent Linux VM with its own init system and state that survives restarts, while regular containers are ephemeral processes. According to the `apple/container` source code, machines store their root filesystem on disk in `~/.container/machines` and boot a full Linux environment, whereas standard containers share the host kernel and disappear when stopped.

### Can I use any Docker image as a container machine?

Any OCI-compliant image containing `/sbin/init` or another init system works as a container machine. Minimal images like `alpine:latest` work for basic testing, but production use typically requires images with `systemd` (like Ubuntu or Fedora) to manage background services properly.

### How do I enable nested virtualization for running Docker inside a container machine?

On Apple Silicon M3+ (macOS 15+), pass `--virtualization` and `--kernel /path/to/vmlinux-kvm` when creating the machine, where the kernel is compiled with `CONFIG_KVM=y`. This exposes `/dev/kvm` inside the VM, allowing you to run nested hypervisors or Docker-in-Docker configurations.

### Where does the container runtime store machine configuration?

Machine configurations persist in [`Sources/ContainerPersistence/MachineConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift) structures stored on disk at `~/.container/machines`. The [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift) file manages global settings and loads the persistent state for all machines, while individual machine metadata includes CPU counts, memory limits, and home-mount paths.