How Container Ensures Network Isolation Between Multiple Containers on macOS 15
Apple's Container tool isolates container traffic by running each Linux container inside a lightweight VM with a dedicated vmnet network interface that is never exposed to the host network stack.
The apple/container project implements strict network isolation for Linux containers on macOS 15 by leveraging the built-in VMnet framework. Unlike traditional container runtimes that share the host network stack, this architecture assigns each container its own virtual network interface and subnet, ensuring traffic remains confined to the container's lightweight VM unless explicitly bridged.
Per-Container Virtual Networks via VMnet
Dedicated vEthernet Interface Allocation
When a container is created, the container-apiserver process communicates with the container-network-vmnet XPC helper to allocate a new vmnet network. According to the implementation in Sources/Plugins/NetworkVmnet/NetworkVmnetHelper.swift, the helper creates a dedicated virtual Ethernet (vEthernet) interface attached exclusively to that container's VM.
Host-Stack Isolation
These interfaces receive unique IP subnets (for example, 192.168.64.0/24) with gateways visible only inside the VM. Because the interface is never exposed to the host network stack, packet forwarding between containers is impossible without explicit configuration. The vmnet framework itself enforces per-client isolation at the macOS virtualization layer.
Runtime Isolation Strategies
IsolatedInterfaceStrategy vs NonisolatedInterfaceStrategy
The runtime driver in Sources/Plugins/RuntimeLinux/RuntimeLinuxHelper+Start.swift registers two distinct strategies keyed by NetworkInterfaceKey(plugin: "container-network-vmnet", variant: …):
- IsolatedInterfaceStrategy: Applied to allocation-only interfaces that belong strictly to a container and remain invisible to the host.
- NonisolatedInterfaceStrategy: Reserved for interfaces the host requires, such as those used by the container's management agent.
NetworkConfiguration Storage
Per-container network metadata—including MAC address, IP address, subnet mask, and gateway—is stored in the NetworkConfiguration object defined in Sources/ContainerResource/Network/NetworkConfiguration.swift. This data configures the container's networking stack without leaking information into the host.
XPC Service Architecture
The container-network-vmnet helper runs as an XPC service, keeping privileged network-setup code isolated from the main runtime. All requests flow through XPC, as implemented in NetworkVmnetHelper.swift, using the vmnet APIs to allocate, reserve, and tear down virtual networks. Because the helper operates as a separate XPC service, vulnerabilities in the container runtime cannot directly manipulate the virtual network interfaces.
Lifecycle Management and Cleanup
When a container stops, container-apiserver instructs the helper to release the allocated network, destroying the vmnet interface and freeing the subnet. The network prune command iterates through all allocated networks and removes unattached interfaces, preventing stale resources from becoming shared. This logic ensures resources defined in Sources/ContainerCommands/Network/NetworkCreate.swift are properly tracked and released.
Practical Configuration Examples
Creating a container with isolated networking:
# Create a container with default isolated network
container create --name my-web --image nginx:latest
# Verify isolation in XPC helper logs
# → allocated attachment [hostname=my-web] [address=192.168.64.2/24] [gateway=192.168.64.1]
Listing per-container networks:
container network list
# Output shows one entry per container:
# my-web 192.168.64.2/24 default
Creating shared networks for explicit communication:
# Create a named network for shared access
container network create shared-net
# Attach multiple containers to the same network
container run --name app1 --network shared-net --image alpine
container run --name app2 --network shared-net --image alpine
When attached to a shared network, both containers receive interfaces on the same vmnet network (shared-net), enabling inter-container communication while maintaining isolation from containers on other networks.
Summary
- Each container receives a dedicated vmnet network interface and subnet via the
container-network-vmnetXPC helper. - IsolatedInterfaceStrategy ensures container interfaces remain invisible to the host network stack.
- Network configuration data is stored in
NetworkConfigurationobjects and applied only within the container's VM. - macOS's vmnet framework enforces per-client isolation at the virtualization layer.
- Lifecycle management automatically releases network resources when containers stop.
Frequently Asked Questions
Does each container get its own IP address on the host network?
No. Each container receives an IP address within a private subnet (such as 192.168.64.0/24) that is only visible inside the container's lightweight VM. The virtual Ethernet interface is not bridged to the host network stack, so the IP address is not routable from the macOS host or other containers unless explicitly configured via a user-defined network.
How does Container prevent containers from seeing each other's traffic?
The container-network-vmnet XPC helper creates distinct vmnet networks for each container using macOS's VMnet framework. Because the framework isolates traffic at the virtualization layer, interfaces allocated via IsolatedInterfaceStrategy in RuntimeLinuxHelper+Start.swift cannot capture or intercept packets from other containers' networks.
Can I run multiple containers that communicate with each other?
Yes. By creating a user-defined network using container network create and attaching multiple containers with the --network flag, the XPC helper allocates a single vmnet network shared among those specific containers. These containers can communicate on the same subnet, while remaining isolated from containers on other networks.
What happens to the network interface when a container stops?
When a container stops, container-apiserver sends a release request to the XPC helper, which destroys the vmnet interface and returns the subnet to the available pool. The network prune command performs garbage collection on any dangling interfaces, ensuring no network resources persist beyond the container's lifecycle.
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 →