How apple/container Achieves Per-Container VM Isolation
Apple's container project isolates each container by running it inside its own Apple Virtualization Framework virtual machine, providing complete hardware-level sandboxing through dedicated kernels, filesystems, and network interfaces.
The apple/container repository implements a container runtime that achieves strong isolation by wrapping every container in a full virtual machine rather than relying on traditional Linux namespaces. This architecture leverages the Apple Virtualization Framework to create per-container VMs with independent kernels, root filesystems, and virtual network interfaces. By examining the source code in Sources/Services/RuntimeLinux/Server/RuntimeService.swift and related components, we can trace exactly how the project transforms Docker-like container commands into isolated virtual machine instances.
VM Lifecycle and Runtime Management
The isolation begins with the RuntimeService actor, defined in Sources/Services/RuntimeLinux/Server/RuntimeService.swift. This service acts as the orchestration layer that creates, boots, and tears down a VZVirtualMachineManager instance for every individual container.
When a container starts, the bootstrap method in Sources/Services/Runtime/RuntimeClient/RuntimeRoutes.swift initiates the VM creation sequence. This method reads the container's ContainerConfiguration, assembles the kernel and initial filesystem, and hands these resources to the VM manager. Each container receives its own dedicated VZVirtualMachineManager, ensuring that processes inside one container cannot see or affect processes in another.
// RuntimeService boots the VM (simplified flow)
public func bootstrap(_ message: XPCMessage) async throws -> XPCMessage {
// Load bundle → kernel + rootfs
let bundle = ContainerResource.Bundle(path: self.root)
var config = try bundle.configuration
let kernel = try bundle.kernel
// Build the VM manager
let vmm = VZVirtualMachineManager(
kernel: kernel,
initialFilesystem: bundle.initialFilesystem.asMount,
rosetta: config.rosetta,
logger: self.log
)
// ... network attachment ...
// Finally, start the VM
try await vmm.start()
return message.reply()
}
Configuration and Resource Limits
Per-container resource constraints are enforced through the ContainerConfiguration struct defined in Sources/ContainerResource/Container/ContainerConfiguration.swift. This configuration stores limits for CPU cores, memory allocation, disk size, and nested virtualization capabilities.
The CLI command container machine create translates user-provided flags into this configuration via Sources/ContainerCommands/Machine/MachineCreate.swift. When the VZVirtualMachineManager instantiates the VM, it enforces these limits, guaranteeing that a runaway container cannot consume more host resources than allocated.
// Create a container "machine" (CLI command: container machine create)
let createCmd = MachineCreate()
try createCmd.run([
"--name", "my-app",
"--cpu", "2",
"--memory", "4G",
"--disk", "10G",
"--nested-virt" // enables nested virtualization on Apple Silicon M-series
])
Kernel and Filesystem Isolation
Each container VM receives its own kernel image and root filesystem, completely isolated from the host's filesystem tree. The ContainerResource.Bundle class in Sources/ContainerResource/Bundle.swift manages these resources, providing access to bundle.kernel and bundle.initialFilesystem.
These filesystem bundles are mounted read-only inside the VM, ensuring that the guest kernel operates within a confined environment. Because each VM boots its own Linux kernel (or other guest OS), containers achieve the same isolation guarantees as full virtual machines rather than shared-kernel containers.
Network Isolation with vmnet
Network isolation is implemented through the vmnet virtual network framework. The ReservedVmnetNetwork class in Sources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swift creates dedicated virtual network interfaces for each container VM.
Each VM receives its own MAC address and IP configuration that is invisible to other VMs. The NonisolatedInterfaceStrategy in Sources/Services/RuntimeLinux/Server/NonisolatedInterfaceStrategy.swift (and related InterfaceStrategy types) determines whether a VM uses a dedicated vmnet interface or a shared host interface, allowing for flexible network topologies while maintaining isolation between containers.
During the bootstrap sequence, the runtime attaches these network interfaces to the VM before starting it:
// Attach network interfaces (via vmnet)
for (idx, netInfo) in try message.networkBootstrapInfos().enumerated() {
let client = ContainerNetworkClient.NetworkClient(id: config.networks[idx].network,
plugin: netInfo.plugin)
let session = client.connect()
let (attachment, _) = try await client.allocate(hostname: …, on: session)
vmm.attach(network: attachment)
}
Guest-Agent Communication
After the VM boots, a lightweight guest-agent runs inside the VM to handle I/O forwarding, health reporting, and socket forwarding (such as SSH authentication sockets). This agent communicates with the host via XPC protocols defined in the Sources/ContainerXPC directory.
The XPC communication keeps the host-side implementation minimal and properly sandboxed. The guest-agent forwards sockets by listening on specific paths inside the VM:
// Guest-side agent (running inside the VM) forwards a socket
let socket = try Socket(path: RuntimeService.sshAuthSocketGuestPath)
try socket.listen()
This architecture ensures that container management operations occur through secure, inter-process communication rather than direct host access.
Summary
- Apple Virtualization Framework: Each container runs inside its own
VZVirtualMachineManagerinstance, providing hardware-level isolation. - Independent Resources: Every VM receives dedicated CPU, memory, kernel images, and root filesystems managed through
ContainerConfigurationandContainerResource.Bundle. - Network Segmentation: The
ReservedVmnetNetworkimplementation assigns unique MAC/IP addresses via vmnet, ensuring network traffic remains isolated between containers. - Secure Communication: A guest-side agent communicates with the host via XPC protocols, enabling socket forwarding and health monitoring without compromising the isolation boundary.
- Docker-like Interface: Despite the VM architecture, the
container machine createcommand provides a familiar CLI experience while generating full VM configurations.
Frequently Asked Questions
Does apple/container use Linux namespaces for isolation?
No. Unlike traditional container runtimes that rely on Linux namespaces and cgroups, apple/container achieves isolation by running each container inside a complete virtual machine using the Apple Virtualization Framework. This provides stronger security boundaries similar to full virtualization rather than process-level isolation.
What virtualization framework does apple/container use?
The project uses Apple's native Virtualization Framework (VZVirtualMachineManager). This framework is specifically designed for Apple Silicon and Intel Macs, allowing the runtime to create lightweight VMs with near-native performance while maintaining strong isolation guarantees.
How does networking isolation work in apple/container?
Each container VM connects to a dedicated vmnet virtual network created by ReservedVmnetNetwork. This assigns a unique MAC address and IP configuration to every container. The InterfaceStrategy determines whether the VM uses a host-only or shared network mode, but in all cases, the network interfaces remain isolated from other containers unless explicitly bridged.
Can I run nested virtualization inside apple/container VMs?
Yes. The ContainerConfiguration supports nested virtualization flags that can be enabled via the --nested-virt option in the container machine create command. This allows running additional virtualization workloads (such as Docker-in-Docker or other hypervisors) inside the container VM on Apple Silicon M-series chips.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →