How Container Integrates with macOS Virtualization and vmnet Frameworks
The apple/container project leverages the Virtualization framework to launch nested macOS VMs for container isolation and the vmnet framework to provide virtual networking, combining VZGenericPlatformConfiguration checks with vmnet_network_create calls to enable container runtime on Apple Silicon.
The apple/container repository enables running Linux containers on macOS by deeply integrating with two low-level Apple frameworks. This integration allows the project to create isolated execution environments through virtual machines while maintaining flexible network connectivity between containers and the host system.
Virtualization Framework Integration
The Virtualization framework provides the foundation for running containerized workloads by allowing the creation of macOS Virtual Machines (VMs) that host the container runtime. This requires nested virtualization support to run containers inside a full VM guest.
Nested Virtualization Requirements
According to the source code in Sources/ContainerCommands/Machine/MachineCapabilities.swift, the project requires specific hardware and software capabilities. The MachineCapabilities.requireNestedVirtualizationSupported() function checks VZGenericPlatformConfiguration.isNestedVirtualizationSupported to ensure the host is an Apple Silicon M3 or newer running macOS 15 or later.
Commands like MachineCreate and MachineSet invoke this verification before starting a container machine. If the check fails, the system throws a ContainerizationError(.unsupported) with a clear message indicating that nested virtualization is not supported on the host.
// Example: Verify host can run nested-virtualized containers
import Virtualization
import ContainerizationError
func ensureNestedVirtualization() throws {
guard VZGenericPlatformConfiguration.isNestedVirtualizationSupported else {
throw ContainerizationError(.unsupported,
message: "nested virtualization is not supported on this host")
}
}
See: MachineCapabilities.swift
vmnet Framework Integration
While the Virtualization framework provides the compute layer, the vmnet framework supplies a custom network stack for the container VM. This allows containers to communicate with the host and external networks through either host-only or NAT (shared) mode configurations.
Network Creation and Reservation
The ReservedVmnetNetwork class in Sources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swift handles the low-level network creation. The implementation follows this sequence:
- Creates a vmnet configuration using
vmnet_network_configuration_create - Configures IPv4/IPv6 subnets for the virtual network
- Disables DHCP using
vmnet_network_configuration_disable_dhcp - Creates the network via
vmnet_network_create - Serializes the network reference for XPC transport using
vmnet_network_copy_serialization
// Example: Create a NAT vmnet network for a container
import vmnet
import Logging
func makeVmnetNetwork(mode: vmnet.operating_modes_t, logger: Logger) throws -> vmnet_network_ref {
var status = vmnet_return_t.VMNET_SUCCESS
let cfg = vmnet_network_configuration_create(mode, &status)
guard let configuration = cfg, status == .VMNET_SUCCESS else {
throw ContainerizationError(.unsupported,
message: "failed to create vmnet config (status \(status))")
}
vmnet_network_configuration_disable_dhcp(configuration)
// Configure subnets here … (omitted for brevity)
guard let network = vmnet_network_create(configuration, &status),
status == .VMNET_SUCCESS else {
throw ContainerizationError(.unsupported,
message: "failed to create vmnet network (status \(status))")
}
return network
}
See: ReservedVmnetNetwork.swift
Interface Strategy Implementation
The NonisolatedInterfaceStrategy class in Sources/Services/RuntimeLinux/Server/NonisolatedInterfaceStrategy.swift bridges the vmnet network reference to the container runtime. The toInterface method deserializes the vmnet reference produced by ReservedVmnetNetwork and constructs a NATNetworkInterface that the container VM uses for connectivity.
// Example: Convert a serialized vmnet reference into a container interface
import vmnet
import ContainerXPC
func interfaceFromXPC(_ message: XPCMessage) throws -> NATNetworkInterface {
var status = vmnet_return_t.VMNET_SUCCESS
guard let networkRef = vmnet_network_create_with_serialization(message.underlying, &status) else {
throw ContainerizationError(.invalidState,
message: "cannot deserialize vmnet reference (status \(status))")
}
return NATNetworkInterface(
ipv4Address: "10.0.0.2",
ipv4Gateway: "10.0.0.1",
reference: networkRef,
macAddress: "02:00:00:00:01:00",
mtu: 1280
)
}
See: NonisolatedInterfaceStrategy.swift
Architectural Flow
The integration between macOS Virtualization and vmnet frameworks follows a structured execution path when users run commands like container machine create:
-
Capability Verification – The
MachineCreatecommand callsMachineCapabilities.requireNestedVirtualizationSupported()to validate that the host supports nested virtualization before provisioning resources. -
Network Configuration – The CLI creates a
NetworkConfigurationstruct specifyingplugin: "container-network-vmnet"and the chosen mode (.hostOnlyor.nat). This configuration is defined inSources/ContainerResource/Network/NetworkConfiguration.swift. -
VM-Net Server Initialization – The runtime launches
ReservedVmnetNetwork(available on macOS 26+), which executes the vmnet creation sequence and serializes the network reference for safe XPC transport. -
Interface Attachment – When the container process starts,
NonisolatedInterfaceStrategy.toInterfacereceives the serialized reference, deserializes it usingvmnet_network_create_with_serialization, and builds theNATNetworkInterfacethat connects to the VM's virtual NIC. -
Container Launch – The Virtualization framework creates the VM with the vmnet network attached as its network interface, providing connectivity as defined by the network configuration.
Key Implementation Files
-
MachineCapabilities.swift – Validates nested virtualization support using
VZGenericPlatformConfiguration.
Sources/ContainerCommands/Machine/MachineCapabilities.swift -
MachineCreate.swift – Orchestrates machine provisioning and invokes capability checks.
Sources/ContainerCommands/Machine/MachineCreate.swift -
ReservedVmnetNetwork.swift – Core vmnet network creation and reservation logic.
Sources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swift -
NonisolatedInterfaceStrategy.swift – Bridges vmnet references to container network interfaces.
Sources/Services/RuntimeLinux/Server/NonisolatedInterfaceStrategy.swift -
NetworkConfiguration.swift – Declares the network plugin identifier and holds vmnet-specific options.
Sources/ContainerResource/Network/NetworkConfiguration.swift
Summary
- Nested virtualization is mandatory for container machines, verified via
VZGenericPlatformConfiguration.isNestedVirtualizationSupportedinMachineCapabilities.swift, requiring Apple Silicon M3+ and macOS 15+. - The vmnet framework provides virtual networking through
ReservedVmnetNetwork, which creates networks usingvmnet_network_configuration_createandvmnet_network_create. - Network interfaces are established when
NonisolatedInterfaceStrategydeserializes vmnet references and constructsNATNetworkInterfaceinstances for container VMs. - Plugin architecture uses
container-network-vmnetas the network driver identifier, configured throughNetworkConfigurationand passed to the runtime. - Separation of concerns isolates capability checks, network creation, and interface management into distinct source files within the repository.
Frequently Asked Questions
What hardware is required to run containers with this integration?
The apple/container project requires Apple Silicon M3 or newer processors running macOS 15 or later. The MachineCapabilities.requireNestedVirtualizationSupported() function explicitly checks VZGenericPlatformConfiguration.isNestedVirtualizationSupported to ensure the host supports nested virtualization before allowing machine creation.
What network modes does the vmnet integration support?
The implementation supports both host-only and NAT (shared) modes. The NetworkConfiguration struct records the chosen mode and passes it to ReservedVmnetNetwork, which configures the vmnet interface accordingly using vmnet_network_configuration_create with the appropriate operating mode parameter.
How does the container VM receive its network configuration?
The network configuration flows through XPC serialization. ReservedVmnetNetwork serializes the vmnet reference using vmnet_network_copy_serialization, then NonisolatedInterfaceStrategy deserializes it with vmnet_network_create_with_serialization to build a NATNetworkInterface that attaches to the VM's virtual NIC.
Where does the capability check occur in the container lifecycle?
The check happens early in the machine creation process. Specifically, MachineCreate.swift calls MachineCapabilities.requireNestedVirtualizationSupported() before provisioning any resources, ensuring that unsupported hardware fails fast with a clear ContainerizationError(.unsupported) message.
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 →