How to Create Linux Containers on macOS Using Apple's Container Tool

Apple's container CLI lets you run OCI-compatible Linux containers on Apple Silicon Macs as lightweight virtual machines without Docker Desktop, using native macOS virtualization and the Apple hypervisor.

Apple's open-source container repository provides a native Swift-based container runtime that brings Docker-like functionality to macOS. Unlike Docker Desktop, this tool creates tiny Linux VMs using the Apple hypervisor framework and VMnet networking, allowing you to build, run, and manage Linux containers directly on your Mac.

Architecture Overview

The container tool consists of several integrated components that work together to provide a seamless Linux container experience on macOS.

Core Components

  • container binary: The front-end CLI written in Swift parses sub-commands (run, build, system) via Swift Argument Parser and forwards requests to the runtime. The progress UI renders in Sources/TerminalProgress/*.

  • Containerization package: This low-level library referenced in Package.swift creates the Linux VM via the Apple hypervisor and mounts OCI images inside it. It handles networking, storage, and Linux capabilities.

  • vminitd init process: A small init inside the VM that starts the OCI container, configures network interfaces, and forwards signals. You can replace this with a custom init image as documented in Docs/how-to.md#custom-init-image.

  • VMnet network: macOS-provided virtual networking that isolates containers while assigning IP addresses in the 192.168.64.x range.

Installation and Setup

The container tool installs as a native, signed macOS package. After installation, you must initialize the system service to create the default VMnet network.

Start the system service:

container system start

This creates the default network configuration stored in ~/.config/container/config.toml, where you can modify defaults such as CPU counts, memory limits, and network subnets.

Running Linux Containers

Once the system service is running, you can execute Linux containers using the container run command.

Run an interactive Alpine Linux shell:

container run --rm -it alpine:latest /bin/sh

The --rm flag automatically removes the container when you exit. By default, containers run with 4 CPUs and 1 GiB of memory, but you can override these limits:

container run --rm --cpus 8 --memory 32g ubuntu:latest uname -a

Networking and Storage Configuration

The tool supports Docker-compatible volume mounts and port forwarding between the host Mac and Linux containers.

Mounting Host Directories

Share files from your Mac into the container:

container run --rm \
  --volume "${HOME}/Desktop/assets:/content/assets" \
  python:3.11-slim ls -l /content/assets

This mounts ~/Desktop/assets to /content/assets inside the container, as implemented in the storage layer defined in Sources/ContainerPersistence/*.

Port Forwarding

Expose container ports on localhost:

container run -d --rm -p 127.0.0.1:8080:8000 \
  node:latest npx http-server -a :: -p 8000

This maps the container's port 8000 to port 8080 on your Mac's loopback interface.

Custom Isolated Networks

Create separate network namespaces for container groups:

container network create foo --subnet 192.168.100.0/24
container run -d --name web --network foo nginx:alpine
container network list

Building Multi-Architecture Images

The container build command executes builds inside a dedicated builder VM, which you can configure independently in Docs/how-to.md#builder-resources.

Build images for multiple architectures simultaneously:

container build \
  --arch arm64 --arch amd64 \
  --tag myrepo/web:latest \
  --file Dockerfile .

This produces an OCI image manifest supporting both Apple Silicon (arm64) and x86-64 (amd64) platforms without requiring QEMU emulation.

Advanced Configuration

Inspecting Container Details

Retrieve machine-readable container metadata:

container inspect web | jq .

This outputs the full JSON descriptor for the container named web, including network settings, mount points, and process status.

Using Custom Init Images

For advanced use cases, replace the default vminitd with a custom init process:


# Build your custom init binary and image

container build -t local/custom-init:latest .

# Run with custom init

container run --init-image local/custom-init:latest \
  alpine:latest echo "hello from custom init"

This workflow is documented in Docs/how-to.md#custom-init-image and allows you to inject specialized initialization logic before the main container process starts.

Summary

  • Apple's container tool creates lightweight Linux VMs using the native Apple hypervisor framework, eliminating the need for Docker Desktop.
  • The architecture centers on the container CLI, Containerization Swift package, and vminitd init process working together to run OCI-compliant containers.
  • Configure defaults in ~/.config/container/config.toml and manage networking via VMnet or custom isolated networks.
  • Build multi-architecture images using container build with the --arch flag for cross-platform compatibility.
  • All source code is available in the apple/container repository, with core logic residing in Sources/ContainerPersistence/* and Sources/TerminalProgress/*.

Frequently Asked Questions

Do I need Docker Desktop installed to use Apple's container tool?

No. The container CLI is a standalone, native macOS application that provides its own runtime. It uses macOS's built-in virtualization frameworks (the Apple hypervisor and VMnet) rather than relying on Docker Desktop or VirtualBox.

How does container networking work on macOS?

The tool uses VMnet, macOS's native virtual network interface, to assign IP addresses (typically 192.168.64.x) to containers. By default, containers connect to the default network, but you can create isolated networks using container network create for better separation between container groups.

Can I build images for Intel Macs from my Apple Silicon Mac?

Yes. The container build command supports multi-architecture builds using the --arch flag. You can specify both --arch arm64 and --arch amd64 in a single command to produce images that run on both Apple Silicon and Intel-based Macs.

Where does the tool store container images and state?

Persistent state and OCI image data are managed by the ContainerPersistence layer (Sources/ContainerPersistence/*). Configuration files live in ~/.config/container/, while the underlying VM state and image layers are stored in the macOS library directory, similar to other container runtimes.

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 →