# Per-Container VM Model Security Isolation in Apple Container vs Shared-VM Approaches

> Discover how Apple's per-container VM model offers hardware-enforced security isolation, preventing shared kernel attacks unlike shared VM approaches.

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

---

**The per-container VM model in Apple Container provides hardware-enforced isolation equivalent to traditional virtual machines by running each container in its own lightweight Linux VM, eliminating shared kernel attack surfaces and cross-container memory leaks inherent in shared-VM approaches.**

The `apple/container` project adopts a unique architectural approach that provisions a dedicated virtual machine for every individual container rather than sharing a single guest kernel among all workloads. This design delivers VM-grade security isolation while maintaining the resource efficiency expected of modern container platforms. By leveraging the macOS Virtualization framework, each container receives its own hardened kernel, private memory space, and isolated device set.

## Hardware-Enforced Memory and CPU Isolation

### Dedicated Memory Boundaries

In the per-container VM model, memory pages are allocated to each VM on demand and remain strictly invisible to other containers. According to the **Technical Overview** in [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md), the hypervisor enforces hardware-level boundaries between virtual machines, preventing the guest kernel from accessing memory belonging to other VMs.

Shared-VM approaches place all containers within the same guest kernel address space. A compromised container can potentially inspect or interfere with sibling containers' memory, requiring user-space sandboxing mechanisms that lack the strength of hardware enforcement.

### CPU Scheduling Isolation

Each per-container VM runs only the processes belonging to its specific container, preventing the guest kernel from scheduling threads across container boundaries. The `container-runtime-linux` helper process defined in [`Sources/Plugins/RuntimeLinux/RuntimeLinuxHelper.swift`](https://github.com/apple/container/blob/main/Sources/Plugins/RuntimeLinux/RuntimeLinuxHelper.swift) (lines 23-25) initializes the VM with dedicated CPU resources, ensuring computational workloads remain strictly partitioned.

Traditional shared-VM architectures rely on cgroups and kernel namespaces for CPU isolation, which have historically been subject to escape vulnerabilities and resource starvation attacks that hardware-isolated VMs prevent.

## Kernel Attack Surface Minimization

The per-container VM dramatically reduces the attack surface by bundling only a minimal set of core utilities and dynamic libraries into each VM image. As implemented in `apple/container`, the VMs run a hardened Kata-Containers kernel specifically optimized for security, isolated from the host kernel and other containers' kernels.

Shared-VM containers must include the full Linux kernel and a large collection of drivers and services to support diverse workloads. This expanded surface area increases vulnerability potential that could compromise all containers simultaneously, whereas a per-container VM breach remains strictly contained within that single instance.

## Filesystem and Device Isolation

### Private Root Filesystems

Each VM maintains a private root filesystem dedicated exclusively to its container. Host data mounts require explicit configuration via `container` bind-mounts, preventing accidental exposure of unrelated host paths. This architecture differs fundamentally from shared-VM approaches where host files are typically mounted once for the entire VM, making paths potentially accessible to any container unless additional sandboxing is layered.

### Device Attachment and Network Segmentation

Devices such as block storage and network interfaces attach to individual VMs rather than being shared across containers. The `vmnet` framework creates isolated virtual networks per container, and on macOS 15, container-to-container communication can be disabled outright ([`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md), lines 65-68).

Shared-VM runtimes present a single set of virtual devices to all containers, where misconfiguration can leak network traffic or device access between workloads.

## Process Space and Runtime Architecture

Each per-container VM runs its own init process (`container-runtime-linux`), which owns the isolated PID namespace for that container. This architecture prevents PID-based attacks on other containers, as process identifiers are not shared across VM boundaries.

The implementation registers each VM with a unique XPC label, ensuring that `container exec` commands communicate directly with the specific VM instance rather than a shared daemon. This contrasts with shared-VM containers that share PID namespaces or limited hierarchies, potentially allowing privilege escalation attacks to affect sibling containers.

## Configuration and Resource Management

Per-container resources are defined in the `[container]` section of [`config.toml`](https://github.com/apple/container/blob/main/config.toml) (documented in [`docs/container-system-config.md`](https://github.com/apple/container/blob/main/docs/container-system-config.md), lines 38-45). The [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift) model materializes these settings into VM parameters, while [`PluginStateRoot.swift`](https://github.com/apple/container/blob/main/PluginStateRoot.swift) manages state directories for each container VM to ensure persistent data isolation.

```bash

# Launch a container with dedicated VM resources

container run -it --name my-app \
    --cpus 2 --memory 1g \
    alpine:latest /bin/sh

```

This command provisions a new lightweight VM with 2 CPUs and 1GB RAM exclusively for `my-app`. When stopped, the VM teardown frees resources without affecting other containers:

```bash

# Execute commands inside the isolated VM via XPC

container exec my-app ps aux

# Stop and destroy the per-container VM

container stop my-app

```

## Summary

- **Hardware isolation**: Each container runs in its own VM with memory and CPU boundaries enforced by the macOS Virtualization framework hypervisor.
- **Minimal kernel surface**: Dedicated hardened Kata-Containers kernels reduce attack surface compared to shared full Linux kernels.
- **Filesystem privacy**: Private root filesystems and explicit bind-mounts prevent accidental host data exposure.
- **Network segmentation**: The `vmnet` framework provides isolated virtual networks per container with optional inter-container communication prohibition.
- **Process isolation**: Unique PID namespaces per VM prevent cross-container process attacks managed through [`RuntimeLinuxHelper.swift`](https://github.com/apple/container/blob/main/RuntimeLinuxHelper.swift).

## Frequently Asked Questions

### How does the per-container VM model affect startup latency compared to shared-VM containers?

The per-container VM model maintains startup speeds comparable to traditional containers despite provisioning full VMs. The lightweight Linux VM images boot rapidly while providing superior security isolation, eliminating the performance-security trade-off inherent in shared-VM approaches that rely on.namespaces alone.

### What happens to persistent data when a per-container VM stops?

The [`PluginStateRoot.swift`](https://github.com/apple/container/blob/main/PluginStateRoot.swift) implementation manages distinct state directories for each container VM, ensuring that persistent data remains isolated between containers even after VM destruction. This architectural separation prevents state leakage that could occur in shared-VM filesystem architectures where multiple containers access the same underlying storage.

### Can a compromised container escape to the host in the per-container VM model?

Escape to the host requires breaking through both the container's process boundaries and the VM's hypervisor isolation, both enforced by the macOS Virtualization framework. This provides defense-in-depth compared to shared-VM approaches where a single kernel exploit could compromise all containers and potentially the host.

### Where is the per-container VM configuration defined?

Resource limits and VM parameters are specified in the `[container]` section of [`config.toml`](https://github.com/apple/container/blob/main/config.toml), parsed by [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift). This configuration maps CLI flags like `--cpus` and `--memory` directly to the underlying VM hardware specifications, ensuring predictable resource allocation per container.