# How Container Leverages the macOS Virtualization Framework for Lightweight Linux VMs

> Discover how Apple's Container project uses the macOS Virtualization framework to run Linux containers as lightweight VMs. Achieve full kernel isolation with minimal resource overhead.

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

---

**Apple's open-source Container project runs each Linux container inside its own lightweight VM using the macOS Virtualization framework, delivering full kernel isolation without the resource overhead of traditional virtualization.**

The `apple/container` repository provides an OCI-compatible runtime that fundamentally reimagines container security on macOS. Rather than using Linux namespaces or process-level sandboxing, the project **leverages the Virtualization framework to run Linux containers as lightweight VMs**, ensuring hardware-enforced boundaries while maintaining the operational simplicity of standard container workflows.

## Mapping Container Configuration to Virtualization Settings

When parsing OCI images and `container run` options, the runtime stores VM-related flags in `ContainerConfiguration.virtualization`. In [`Sources/ContainerBuild/Builder.swift`](https://github.com/apple/container/blob/main/Sources/ContainerBuild/Builder.swift) (lines 93-98), the build process translates high-level container specifications into low-level Virtualization framework parameters, including kernel selection and initial filesystem configuration.

## Initializing the Virtual Machine Manager

The core bootstrap logic resides in [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) (lines 162-169). Here, the runtime constructs a **VZVirtualMachineManager**—the high-level wrapper around the Virtualization framework—by passing the Linux kernel, initial filesystem mount, Rosetta translation settings, and logger instance.

```swift
let vmm = VZVirtualMachineManager(
    kernel: kernel,
    initialFilesystem: bundle.initialFilesystem.asMount,
    rosetta: config.rosetta,
    logger: self.log
)

```

## Injecting the VM into LinuxContainer

The manager instance is then passed to the **LinuxContainer** constructor in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift) (lines 53-56). This concrete container implementation serves as the primary interface between the OCI runtime and the virtualized environment, configuring CPU count, memory allocation, and mount points through a trailing closure.

```swift
let container = try LinuxContainer(
    id,
    rootfs: rootfs,
    vmm: vmm,
    logger: self.log
) { czConfig in
    // configure CPUs, memory, mounts, etc.
}

```

## Boot Sequence and Kernel Isolation

After instantiation, calling `container.create()` boots the VM, followed by `container.start()` to launch the init process. As documented in [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md) (lines 36-57), each VM runs a minimal Linux kernel provided by Apple, offering **full kernel-level isolation** that prevents container escape vulnerabilities inherent in shared-kernel architectures.

## Memory Efficiency Through Ballooning

Unlike traditional VMs that consume their full allocated RAM, Container utilizes **memory ballooning** to maintain efficiency. According to [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md) (lines 55-59), the Virtualization framework allows each VM to shrink its resident set, releasing unused memory back to macOS. This ensures containers typically consume far less RAM than their allocation limits.

## Network Device Attachment

The Virtualization framework manages attached devices through specialized strategies. In [`Sources/ContainerPlugin/NonisolatedInterfaceStrategy.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPlugin/NonisolatedInterfaceStrategy.swift) (lines 23-28), the runtime configures network interfaces that are exposed to the container, enabling seamless connectivity without breaking the VM security boundary.

## Complete Implementation Example

The following Swift code demonstrates the end-to-end workflow from bundle initialization to process execution:

```swift
import Containerization
import ContainerRuntimeClient
import Logging
import Virtualization

// 1️⃣ Load the container bundle (contains kernel, rootfs, config, etc.)
let bundle = ContainerResource.Bundle(path: URL(fileURLWithPath: "/var/run/container/myapp"))
try bundle.createLogFile()

// 2️⃣ Build the VM manager from the bundle's kernel
let kernel = try bundle.kernel
let vmm = VZVirtualMachineManager(
    kernel: kernel,
    initialFilesystem: bundle.initialFilesystem.asMount,
    rosetta: false,
    logger: Logger(label: "myapp")
)

// 3️⃣ Create the LinuxContainer that wraps the VM
let rootfs = try bundle.containerRootfs.asMount
let container = try LinuxContainer(
    "myapp",
    rootfs: rootfs,
    vmm: vmm,
    logger: Logger(label: "myapp")
) { cfg in
    cfg.cpus = 2
    cfg.memoryInBytes = 512 * 1024 * 1024   // 512 MiB
    cfg.hostname = "myapp"
}

// 4️⃣ Boot the VM and start the init process inside it
try container.create()
try container.start()

// 5️⃣ Run a command inside the container (equivalent to `container exec`)
let proc = try await container.exec(
    "myapp",
    configuration: LinuxProcessConfiguration(
        arguments: ["/bin/bash", "-c", "echo Hello from the VM!"]
    )
)
let exitCode = try await proc.wait()
print("Process exited with code \(exitCode)")

```

## Summary

- **VM-per-container model**: Each Linux container runs in its own lightweight VM via **VZVirtualMachineManager**, providing hardware-level isolation.
- **Configuration pipeline**: OCI specs translate to Virtualization settings in [`Builder.swift`](https://github.com/apple/container/blob/main/Builder.swift), then instantiate VMs in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift).
- **Resource optimization**: **Memory ballooning** ensures VMs only consume RAM proportional to actual usage, not allocation limits.
- **Device management**: Network interfaces attach through `NonisolatedInterfaceStrategy`, maintaining security while enabling connectivity.
- **Kernel isolation**: Apple-provided minimal Linux kernels prevent container escape while supporting standard Linux workloads.

## Frequently Asked Questions

### How does Container differ from Docker or traditional Linux runtimes?

Traditional runtimes rely on Linux namespaces and cgroups for process-level isolation on a shared kernel. Container instead **leverages the Virtualization framework to run Linux containers as lightweight VMs**, creating hardware-enforced boundaries with separate kernels that eliminate shared-kernel attack vectors.

### Where is VZVirtualMachineManager initialized in the source code?

The manager is constructed in [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) at lines 162-169. This initialization accepts the kernel bundle, initial filesystem, Rosetta configuration, and logger before being injected into the **LinuxContainer** constructor at lines 53-56.

### How does Container optimize memory usage across multiple VMs?

According to [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md) (lines 55-59), the implementation utilizes **memory ballooning** via the Virtualization framework. This allows each VM to return unused memory to the host macOS system, ensuring that containers consume resources proportional to their actual workload rather than their maximum allocation.

### How are network interfaces exposed to container VMs?

Network device attachment is handled by `NonisolatedInterfaceStrategy` in [`Sources/ContainerPlugin/NonisolatedInterfaceStrategy.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPlugin/NonisolatedInterfaceStrategy.swift) (lines 23-28). This strategy configures Virtualization framework network devices that appear as standard Ethernet interfaces inside the guest Linux kernel.