| name | container |
| description | Guide for using Apple Container CLI to run Linux containers on Apple silicon Macs (macOS 26+). Use when managing OCI containers, building images, configuring networks/volumes, running long-lived Linux machines with container machine, or working with container system services on macOS. |
| license | MIT |
Apple Container CLI
This skill activates when working with Apple Container for running Linux containers natively on Apple silicon Macs.
When to Use This Skill
Activate when:
- Running Linux containers on macOS 26+ with Apple silicon
- Managing container lifecycle (run, stop, exec, logs, inspect)
- Building OCI-compatible container images
- Managing container images (pull, push, tag, save, load)
- Configuring container networks and volumes
- Managing the container system service
- Running long-lived Linux machine environments with
container machine (1.0.0+)
- Migrating between Apple Container versions (0.5.x to 1.0.0)
What is Apple Container?
Apple Container is a macOS-native tool for running Linux containers as lightweight virtual machines on Apple silicon:
- Swift-based: Built on Apple's Virtualization.framework
- OCI-compatible: Produces and runs standard OCI container images
- Apple silicon only: Requires Apple silicon Mac (M1 or later)
- Stable 1.0: Currently at version 1.0.0 (released 2026-06-09); 0.x minor releases carried frequent breaking changes — see Version Differences below when upgrading
- Lightweight VMs: Each container runs as a lightweight Linux VM
Prerequisites
- macOS 26 or later (Tahoe)
- Apple silicon Mac (M1, M2, M3, M4 series)
- Install via signed
.pkg from GitHub releases
System Management
Manage the container system service that runs in the background:
container system start
container system stop
container system status
container system status --format json
container system version
container system logs
container system df
System Configuration (TOML, 1.0.0+)
⚠ BREAKING — 1.0.0: A TOML configuration file replaces the UserDefaults-backed system properties. container system property get, set, and clear are REMOVED. Migrate stored property values into config.toml, then restart the service.
Configuration lives at ~/.config/container/config.toml, with a package-shipped fallback at <installRoot>/etc/container/config.toml (first match wins; missing keys fall back to built-in defaults):
mkdir -p ~/.config/container
touch ~/.config/container/config.toml
[container]
cpus = 8
memory = "4g"
[dns]
domain = "test"
Top-level tables: [container], [dns], [build], [kernel], [network], [registry], [vminit].
Apply changes by restarting the service:
container system stop
container system start
container system property list (alias ls) remains as a read-only view of the merged configuration:
container system property list --format json
System DNS
Manage DNS configuration for containers:
container system dns create <name> <ip>
container system dns delete <name>
container system dns list
Custom Kernel
Set a custom Linux kernel for containers:
container system kernel set <path>
container system kernel set --force <path>
Container Lifecycle
Run Containers
container run -it ubuntu:latest /bin/bash
container run -d --name myapp nginx:latest
container run -d -p 8080:80 nginx:latest
container run -v /host/path:/container/path ubuntu:latest
container run -e FOO=bar -e BAZ=qux myimage:latest
container run --rm -it alpine:latest /bin/sh
container run -d --name web -p 8080:80 -v ./html:/usr/share/nginx/html -e ENV=prod nginx:latest
container run -d --name app --cpus 2 --memory 4g myapp:latest
container run --read-only -v tmpdata:/tmp myapp:latest
container run --rosetta -it amd64-image:latest /bin/bash
container run --dns 8.8.8.8 --dns-search example.com myapp:latest
container run --mac-address 02:42:ac:11:00:02 --network mynet myapp:latest
container run -e API_URL=http://host.docker.internal:3000 myapp:latest
container run --init-image custom-init:latest -d --name app myapp:latest
container run --runtime myruntime -d --name app myapp:latest
container run --init -d --name app myapp:latest
container run --cap-add NET_ADMIN myimage:latest
container run --cap-drop ALL --cap-add NET_BIND_SERVICE myimage:latest
container run --shm-size 1g -d --name app myapp:latest
Custom stop signals are set on container stop, not container run (1.0.0+):
container stop --signal SIGTERM app
Manage Running Containers
container list
container ls
container list --all
container start <name-or-id>
container stop <name-or-id>
container kill <name-or-id>
container delete <name-or-id>
container rm <name-or-id>
container exec -it <name-or-id> /bin/bash
container exec -d <name-or-id> /usr/bin/background-task
container logs <name-or-id>
container logs --follow <name-or-id>
container inspect <name-or-id>
container cp <name-or-id>:/path/in/container ./local-path
container cp ./local-file <name-or-id>:/path/in/container
container stats
container prune
Export Container (0.10.0+)
container export <name-or-id> -o exported.tar
container export <name-or-id> -t myimage:snapshot
Create Without Starting
container create --name myapp nginx:latest
container start myapp
Container Machines (1.0.0+)
Machines are long-lived Linux environments with tight host integration — a full Linux system with init support, not an ephemeral application container. Use machines for "edit on the Mac, build inside Linux" workflows, running system services under systemd, and testing across multiple distributions. The subcommand alias is m (container m ls = container machine ls).
Isolation caveat: A machine auto-mounts the host home directory at /Users/<username> inside the VM. That tight host integration makes machines a development convenience, NOT an isolation boundary for untrusted workloads — run untrusted agents in regular containers or a dedicated sandboxing substrate instead.
container machine create alpine:latest --name dev
container machine run -n dev uname -a
container machine run -n dev -- cat /proc/cpuinfo
container machine run -n dev
container machine set-default dev
container machine run
container machine ls
container machine inspect dev
container machine stop dev
container machine rm dev
container machine set -n dev cpus=4 memory=8G
container machine stop dev
container machine run -n dev -- nproc
The machine maps the host user automatically: the host home directory is mounted at /Users/<username> inside the machine and the machine user matches the host UID/GID.
Custom Machine Images
Machine images require /sbin/init (a process supervisor such as systemd). An optional first-boot script at /etc/machine/create-user.sh receives CONTAINER_UID, CONTAINER_GID, CONTAINER_USER, CONTAINER_HOME, and CONTAINER_MACHINE_ID:
container build -t local/ubuntu-machine:latest .
container machine create local/ubuntu-machine:latest --name ubuntu
See templates/1.0.0/commands.md and the upstream machine guide for the full machine reference.
Image Management
container image pull ubuntu:latest
container image pull --platform linux/arm64 nginx:latest
container image pull --arch arm64 --os linux nginx:latest
container image list
container image ls
container image tag ubuntu:latest myregistry/ubuntu:v1
container image push myregistry/ubuntu:v1
container image save ubuntu:latest -o ubuntu.tar
container image load -i ubuntu.tar
container image delete ubuntu:latest
container image delete --force ubuntu:latest
container image inspect ubuntu:latest
container image prune
container image prune -a
Platform Flags
When pulling or building images, specify the target platform:
--platform linux/arm64
--arch arm64
--os linux
--scheme oci
Architecture aliases (0.8.0+): amd64=x86_64, arm64=aarch64
Default platform (0.11.0+): Set CONTAINER_DEFAULT_PLATFORM to avoid specifying --platform on every pull/build:
export CONTAINER_DEFAULT_PLATFORM=linux/arm64
Build
Build OCI-compatible images from Dockerfiles or Containerfiles:
container build -t myimage:latest .
container build -t myimage:latest -f Dockerfile.prod .
container build -t myimage:latest --build-arg VERSION=1.0 .
container build -t myimage:latest --no-cache .
container build -t myimage:latest --target builder .
container build -t myimage:latest --platform linux/arm64 .
container build -t myimage:latest -o type=local,dest=./output .
container build -t myimage:latest -t myimage:v1.0 .
container build -t myimage:latest --network none .
container build -t myimage:latest --dns 8.8.8.8 .
container build -t myimage:latest -f - . <<EOF
FROM alpine:latest
RUN echo "hello"
EOF
Note: When no Dockerfile is found, the builder falls back to Containerfile (0.6.0+).
Builder Management
The builder runs as a separate process:
container builder start
container builder stop
container builder delete
container builder status
Network Management
Create and manage container networks:
container network create mynetwork
container network create --subnet 10.0.0.0/24 mynetwork
container network create --labels env=dev mynetwork
container network list
container network inspect mynetwork
container network delete mynetwork
container network prune
Network capabilities (0.8.0+): Full IPv6 support. Host-only and isolated network modes available in 0.9.0+ (verify flag syntax with container network create --help). mtu network attachment option available in 0.11.0+.
Multi-Container Networking
container network create app-net
container run -d --name db --network app-net postgres:latest
container run -d --name web --network app-net -p 8080:80 myapp:latest
container exec web curl http://db:5432
Volume Management
Create and manage persistent volumes:
container volume create mydata
container volume create -s 10G mydata
container volume create --label env=prod mydata
container volume create --opt type=tmpfs mydata
container volume create --journal mydata
container volume list
container volume inspect mydata
container volume delete mydata
container volume prune
Using Volumes
container run -v mydata:/data myimage:latest
container run -v /host/path:/container/path myimage:latest
container run -v mydata:/data:ro myimage:latest
Registry
Authenticate with container registries:
container registry login <registry-url>
container registry logout <registry-url>
container registry list
Note: In 0.5.0, the keychain ID changed from com.apple.container to com.apple.container.registry. Re-login is required after upgrading from 0.4.x.
Version Differences (0.5.0 to 1.0.0)
Breaking Changes
| Version | Change | Migration |
|---|
| 0.6.0 | Image store directory moved from .build to builder | Update paths referencing .build |
| 0.7.0 | --disable-progress-updates removed | Use --progress none|ansi instead |
| 0.8.0 | Client API reorganization | Update API consumers |
| 0.8.0 | Subnet allocation defaults changed | Review network configurations |
| 0.10.0 | ClientContainer reworked as generic client | Update API consumers for generic client interface |
| 0.10.0 | Bundle creation moved to SandboxService | Move bundle creation code from main container ops |
| 0.10.0 | Multiple network plugins support | Review network configuration for multi-plugin model |
| 0.12.0 | Default Linux capability set REDUCED | Delete & recreate all existing containers; use --cap-add to restore needed capabilities |
| 0.12.0 | Builder-shim gRPC protocol changed | Incompatible with pre-0.12.0 clients — update all builder clients |
| 1.0.0 | TOML config file replaces UserDefaults-backed system properties | Move property set values into ~/.config/container/config.toml; property get/set/clear are removed |
| 1.0.0 | Structured (JSON/YAML/TOML) output shape changed for container/image/network/volume ls and inspect | Update scripts that parse structured output |
| 1.0.0 | Application major version 0 XPC API compatibility removed | Update XPC API consumers |
⚠ BREAKING — 0.12.0 capability change: The default Linux capability set was reduced. Users MUST delete and recreate existing containers to apply the new defaults. Use --cap-add to restore capabilities; use --cap-drop to further restrict them. See 0.12.0 template for details.
Required Migrations
- 0.12.0: Delete and recreate all existing containers (reduced default capability set); add
--cap-add for containers needing elevated capabilities
- 0.12.0: Update builder clients (gRPC protocol changed, incompatible with older clients)
- 1.0.0: Move
container system property set values into ~/.config/container/config.toml, then restart the service
- 1.0.0: Update automation that parses
ls/inspect structured output (shape changed)
The full per-release feature history, the complete 0.5.x-to-1.0.0 migration checklist, and the dependency matrix live in references/version-history.md. The exhaustive per-command flag reference lives in references/command-reference.md.
See templates/<version>/commands.md for version-specific details (0.4.1, 0.5.0, 0.6.0, 0.7.0, 0.8.0, 0.9.0, 0.10.0, 0.11.0, 0.12.0, 0.12.3, 1.0.0).
Scripts
This skill includes focused Nushell scripts for container management:
container-system.nu
System service management with health checks:
nu scripts/container-system.nu start
nu scripts/container-system.nu status
nu scripts/container-system.nu health
nu scripts/container-system.nu df
nu scripts/container-system.nu version
container-images.nu
Image lifecycle operations:
nu scripts/container-images.nu list
nu scripts/container-images.nu pull ubuntu:latest
nu scripts/container-images.nu build -t myimage:latest .
nu scripts/container-images.nu prune
container-lifecycle.nu
Container run/stop/exec/logs/export:
nu scripts/container-lifecycle.nu ps
nu scripts/container-lifecycle.nu run ubuntu:latest
nu scripts/container-lifecycle.nu logs mycontainer
nu scripts/container-lifecycle.nu exec mycontainer /bin/bash
nu scripts/container-lifecycle.nu export mycontainer -o exported.tar
container-cleanup.nu
Prune and disk usage:
nu scripts/container-cleanup.nu prune-all
nu scripts/container-cleanup.nu prune-containers
nu scripts/container-cleanup.nu df
Mise Tasks
Copy templates/mise.toml to add container management tasks to any project:
mise container:start
mise container:stop
mise container:status
mise container:run
mise container:ps
mise container:images
mise container:build
mise container:prune
mise container:health
mise container:df
mise container:version
Common Workflows
Quick Start
container system start
container run -it --rm ubuntu:latest /bin/bash
container ls
Build and Run
container build -t myapp:latest .
container run -d --name myapp -p 8080:80 myapp:latest
container logs --follow myapp
Multi-Container with Networking
container network create mynet
container run -d --name postgres --network mynet \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
container run -d --name app --network mynet \
-p 3000:3000 \
-e DATABASE_URL=postgres://postgres:secret@postgres:5432/mydb \
myapp:latest
Persistent Data with Volumes
container volume create appdata
container run -d --name db -v appdata:/var/lib/data mydb:latest
container rm db
container run -d --name db2 -v appdata:/var/lib/data mydb:latest
Troubleshooting
System Not Started
container system status
container system start
container system logs
Image Pull Failures
container system status
container image pull --platform linux/arm64 <image>
container registry login <registry>
Volume Permission Issues
container volume list
container volume inspect <name>
container run -u 1000:1000 -v myvol:/data myimage:latest
Builder Issues
container builder status
container builder stop
container builder start
container builder delete
container builder start
Key Principles
- Stable 1.0: The CLI surface stabilized at 1.0.0; the 0.x-to-1.0.0 migration is breaking (TOML config, structured-output shape)
- Apple silicon only: No Intel Mac support
- macOS 26+ required: Not available on earlier macOS versions
- OCI-compatible: Standard container images work as expected
- Lightweight VMs: Each container is an isolated lightweight VM
- System service: Start the system service before running containers
- Verify, never fabricate: Confirm flags against
container <cmd> --help before scripting them — see /core:anti-fabrication