# How to Run Linux Containers as Lightweight VMs on Mac

> Effortlessly run Linux containers as lightweight VMs on Mac using Apple's container CLI. Achieve full VM isolation with minimal resource overhead for your development workflow.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: getting-started
- Published: 2026-07-03

---

**The `container` CLI runs every Linux container inside its own dedicated lightweight virtual machine using Apple's open-source Containerization framework and the macOS Virtualization APIs, delivering full VM isolation with near-container resource overhead.**

The `apple/container` repository implements a novel approach to containerization on macOS by abandoning the shared-VM model in favor of per-container virtualization. Instead of running all containers within a single Linux VM, this tool spins up a dedicated lightweight VM for each container, leveraging native macOS frameworks to combine the security boundaries of virtual machines with the startup speed and efficiency of traditional containers.

## Architecture Overview

The lightweight-VM architecture relies on tight integration with macOS system frameworks to achieve isolation without the bloat of traditional virtualization.

### Per-Container VM Isolation

According to [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md), each container operates inside its own minimal Linux VM rather than sharing a single host. This design provides **full VM isolation** for security and privacy while maintaining a tiny memory footprint comparable to standard containers. The Virtualization framework handles the creation and management of these ephemeral VMs.

### macOS Framework Integration

The implementation utilizes two core macOS frameworks:

- **Virtualization framework**: Creates and manages the minimal Linux VMs that host individual containers (referenced in [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md) lines 24-31)
- **vmnet framework**: Supplies virtual network interfaces that each VM-based container attaches to automatically (referenced in [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md) lines 36-38)

### XPC Helper Architecture

Multiple XPC helpers bridge the CLI to the underlying VMs, as documented in [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md) lines 45-48:

- `container-apiserver`: Handles the main API surface and container lifecycle
- `container-runtime-linux`: Manages the Linux-specific runtime operations
- `container-network-vmnet`: Coordinates network interface provisioning

The [`Sources/ContainerPlugin/ServiceManager.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPlugin/ServiceManager.swift) file implements the Launchd service that starts `container-apiserver` when you run `container system start`, while [`Sources/ContainerPlugin/PluginLoader.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPlugin/PluginLoader.swift) dynamically loads these XPC helpers to manage per-container VMs. Registry credentials are stored securely in the macOS Keychain, and unified logging captures both VM boot and container runtime events.

## Installation and Setup

Install the CLI via Homebrew and initialize the container system:

```bash

# Install the container CLI

brew install container-cli

# Start the container system (launches container-apiserver via Launchd)

container system start

```

Starting the system creates the necessary XPC services and prepares the virtualization environment. The [`Package.swift`](https://github.com/apple/container/blob/main/Package.swift) file declares the Swift package dependencies and links to the underlying `containerization` runtime that powers the VM abstraction.

## Running Your First Lightweight-VM Container

Once the system is running, the workflow remains OCI-compatible. You can pull images from any registry and run them inside dedicated VMs:

```bash

# Pull a Linux image from Docker Hub

container pull docker.io/alpine:latest

# Run an interactive shell inside a dedicated lightweight VM

container run --rm -it alpine:latest sh

```

When you execute `container run`, the CLI coordinates with `container-runtime-linux` to spin up a fresh Linux VM, mount the requested image layers, and start your process inside the isolated environment. The VM terminates automatically when the container exits.

## Resource Configuration and Networking

### CPU and Memory Limits

Configure VM resources using flags documented in [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md) lines 10-16. The defaults allocate 4 CPUs and 1 GiB of RAM per container:

```bash

# Run with custom resource limits

container run --rm -it \
    --cpus 8 \
    --memory 4g \
    alpine:latest sh

```

### Network Configuration

By default, containers attach to the `vmnet` network for seamless host connectivity. On macOS 26+, you can create isolated networks using the `container network create` command (documented in [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md) lines 7-13):

```bash

# Create an isolated network

container network create isolated

# Run a container on the isolated network

container run -d --name db \
    --network isolated \
    postgres:15

```

### Nested Virtualization

Apple Silicon M3+ Macs support running nested VMs inside containers. Enable this feature using the `--virtualization` flag (documented in [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md) lines 15-22):

```bash

# Run a container with nested virtualization enabled

container run --virtualization \
    --kernel /path/to/linux-kernel-with-virt \
    ubuntu:latest \
    sh -c "dmesg | grep kvm"

```

## Additional CLI Operations

Manage containers and inspect VM-backed workloads using standard commands:

```bash

# Publish a port from the VM to the host

container run -d --name web \
    -p 127.0.0.1:8080:80 \
    nginx:latest

# Inspect container metadata (JSON output)

container inspect web | jq .

# Monitor resource usage in real-time

container stats web

# Stop and remove the container (terminates the VM)

container stop web && container rm web

```

## Key Implementation Files

Understanding the source structure helps when debugging or extending the tool:

- [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md): Describes the VM isolation architecture and framework integration
- [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md): Practical guidance for resource configuration, networking, and nested virtualization
- [`Sources/ContainerPlugin/ServiceManager.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPlugin/ServiceManager.swift): Implements Launchd service management for the API server
- [`Sources/ContainerPlugin/PluginLoader.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPlugin/PluginLoader.swift): Loads XPC helpers that manage per-container VMs
- [`Package.swift`](https://github.com/apple/container/blob/main/Package.swift): Declares Swift package dependencies and links to the Containerization runtime

## Summary

- **Per-container VMs**: Each Linux container runs in its own lightweight VM rather than a shared host, providing superior isolation
- **Native macOS integration**: Built on the Virtualization and vmnet frameworks, with XPC helpers bridging the CLI to the VM layer
- **OCI compatibility**: Standard `pull`, `run`, and `build` commands work against any container registry
- **Resource control**: Configure CPU and memory limits per VM using `--cpus` and `--memory` flags
- **Advanced features**: Support for isolated networks (macOS 26+) and nested virtualization (Apple Silicon M3+)

## Frequently Asked Questions

### How does this differ from Docker Desktop on Mac?

Docker Desktop traditionally uses a single shared Linux VM to host all containers, while `apple/container` creates a dedicated lightweight VM for every container. This provides stronger isolation boundaries at the VM level, though it requires more careful resource management since each container allocates its own virtualized memory and CPU quota.

### What are the minimum system requirements for running lightweight-VM containers?

You need macOS with Apple Silicon (M1 or later) or Intel support, though nested virtualization features require M3 or newer. The tool relies on the macOS Virtualization framework, which requires relatively recent macOS versions compatible with the `containerization` package linked in [`Package.swift`](https://github.com/apple/container/blob/main/Package.swift).

### How do I configure resource limits for the lightweight VMs?

Use the `--cpus` and `--memory` flags when running `container run`, as implemented in the CLI and documented in [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md). The defaults are 4 vCPUs and 1 GiB of RAM, but you can specify higher allocations to match your workload requirements. Each VM operates within these constraints independently.

### Can I run nested VMs inside these containers?

Yes, on Apple Silicon M3+ Macs, you can enable nested virtualization using the `--virtualization` flag combined with a custom kernel that supports KVM. This allows you to run additional virtual machines or virtualization workloads inside your container's dedicated VM, as detailed in [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md) lines 15-22.