# How Running Each Container in Its Own VM Enhances Security Isolation

> Discover how running each container in its own VM boosts security isolation. Learn about hardware-grade separation, independent kernels, and strict sandboxing with the Apple Virtualization framework.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: internals
- Published: 2026-06-19

---

**Running each container in its own VM provides full hardware-grade isolation through independent guest kernels, dedicated memory spaces, and strict sandboxing via the Apple Virtualization framework, ensuring that a compromise in one container cannot affect others or the host.**

The `apple/container` repository implements a **lightweight-VM-per-container** architecture that diverges from traditional container runtimes. Instead of sharing a single Linux VM among all workloads, each container is launched inside its own minimal virtual machine. This design ensures that running each container in its own VM delivers the security guarantees of full virtualization while maintaining resource efficiency comparable to standard containers.

## What Is the Lightweight-VM-Per-Container Model?

Unlike macOS-based container runtimes that rely on a shared Linux kernel, the `container` tool creates a new minimal VM for every container instance. According to [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md), this approach leverages the **Apple Virtualization framework** to spawn independent guest environments. Each VM contains only the essential core utilities and dynamic libraries required for the container runtime, eliminating unnecessary services that could expand the attack surface.

## Security Benefits of VM-Level Isolation

### Full VM Isolation via Independent Guest Kernels

Each container executes within its own guest kernel, memory space, and CPU context. As implemented in [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift), the runtime service creates distinct page tables and kernel instances for every container. A compromise in one container cannot directly access the memory or devices of another container or the host system, providing the same isolation guarantees as traditional virtual machines.

### Reduced Attack Surface with Minimal VM Images

The VM image contains only a minimal set of core utilities required for operation. By omitting unnecessary services and binaries from the guest environment, the `container` runtime significantly lowers the number of exploitable components available to attackers. This minimalism is explicitly designed into the security model documented in [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md).

### Strong Sandboxing via macOS Virtualization Frameworks

The Apple Virtualization framework enforces strict separation between guest VMs and the host macOS system. The **vmnet framework** provides a dedicated virtual network interface per VM, preventing cross-container network traffic unless explicitly enabled. This network isolation ensures that malicious traffic or scanning from one compromised container cannot reach sibling containers or the host.

### Independent Lifecycle and Failure Containment

The **`container-runtime-linux`** XPC service manages the complete lifecycle of each VM—creation, boot, and teardown—independently. If a container's VM crashes or is killed, the failure remains confined to that specific VM and does not affect other running containers or the host daemon. This containment strategy is critical for multi-tenant environments where workload stability varies.

### Memory Containment and Resource Boundaries

Memory allocated to a container is backed by the VM's own page tables, creating hard boundaries around RAM consumption. While current macOS memory-ballooning capabilities are limited, the VM architecture prevents a container from exhausting host memory without the host's explicit awareness. Configuration settings in [`Sources/ContainerPersistence/MachineConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift) control these resource limits per container, including CPU counts and nested-virtualization flags.

## Technical Implementation in the Container Runtime

The isolation mechanics are implemented across several key components:

- **[`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift)**: Located in `Sources/Services/RuntimeLinux/Server/`, this file implements the XPC service that creates, boots, and manages the VM for each container.
- **[`MachineCreate.swift`](https://github.com/apple/container/blob/main/MachineCreate.swift)**: Found in `Sources/ContainerCommands/Machine/`, this handles CLI flags such as `--virtualization` that control VM creation parameters per container.
- **[`MachineConfig.swift`](https://github.com/apple/container/blob/main/MachineConfig.swift)**: Stored in `Sources/ContainerPersistence/`, this manages configuration including CPU counts, memory limits, and nested-virtualization settings that directly impact isolation strength.

## Verifying VM Isolation with CLI Commands

The `container` CLI exposes the underlying VM architecture through several commands. These demonstrate that each container operates as a distinct virtual machine:

```bash

# Run a container – a dedicated lightweight VM is created automatically

container run -it docker.io/library/alpine:latest /bin/sh

```

```bash

# List the VMs (machines) that are backing running containers

container machine list

# Example output:

# ID   STATE   CPU   MEMORY   IMAGE

# 1    running 2     2GiB    vminitd‑latest

```

```bash

# Inspect a specific VM to see its isolation settings

container machine inspect 1 | jq '.config.virtualization'

# Returns: true   # nested virtualization flag (if enabled)

```

```bash

# Execute a command inside the VM that backs a container

container machine exec 1 -- /usr/bin/ps aux

```

## Summary

- **Running each container in its own VM** provides hardware-grade isolation through independent guest kernels and memory spaces managed by the Apple Virtualization framework.
- The minimal VM image design reduces the attack surface by excluding unnecessary services and binaries from the guest environment.
- Network isolation via the vmnet framework prevents cross-container traffic unless explicitly configured.
- The `container-runtime-linux` service ensures that crashes or compromises remain confined to individual VMs without affecting sibling containers or the host.
- CLI commands like `container machine list` and `container machine inspect` expose the VM-layer architecture for verification and debugging.

## Frequently Asked Questions

### How does the VM-per-container model differ from Docker Desktop's approach on macOS?

Docker Desktop traditionally uses a single shared Linux VM to host all containers, meaning a kernel exploit or container breakout could potentially access other containers. In contrast, `apple/container` creates a separate lightweight VM for every container, ensuring that each workload has its own isolated kernel instance and cannot directly access sibling containers' memory or devices.

### What happens if a container's VM crashes?

If a container's VM crashes or is killed, the failure is contained entirely within that specific VM. The [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift) implementation ensures that the host daemon and other running containers continue operating normally, as each container's lifecycle is managed independently.

### Does running each container in its own VM impact performance?

While there is some overhead compared to sharing a single VM, the Apple Virtualization framework minimizes this through lightweight virtual machines and efficient resource management. Boot times and overhead remain comparable to traditional containers, though memory usage is higher due to separate kernel instances per container.

### How can I verify that my container is running in its own VM?

Use the `container machine list` command to see all VM instances backing your containers, then run `container machine inspect <ID>` to view the specific isolation configuration, including CPU, memory allocation, and Virtualization framework flags.