Networking Capabilities of apple/container: Complete Guide to macOS Container Networking
The apple/container repository provides a complete, extensible networking stack for macOS containers featuring NAT and host-only modes, vmnet-based runtime implementation, XPC-based client communication, and a plugin-first architecture for custom network drivers.
The apple/container project delivers a sophisticated networking subsystem that defines the networking capabilities of apple/container for containerized workloads on macOS. This Swift-based implementation separates network definition from runtime execution, enabling developers to create isolated virtual networks using Apple's native vmnet framework. Understanding these networking capabilities is essential for anyone deploying containers on macOS with custom network configurations.
Network Configuration and Resource Model
Container networks in apple/container are defined by the NetworkConfiguration type, which provides a persistent, JSON-serializable description of network properties. Located in Sources/ContainerResource/Network/NetworkConfiguration.swift, this structure captures the essential parameters required to instantiate a virtual network.
Key configuration properties include:
name– A unique identifier that serves as both the display name and internal ID, validated viaNetworkResource.nameValid(name).mode– Specifies the network topology as eithernat(default) orhostOnly, defined inSources/ContainerResource/Network/NetworkMode.swift.ipv4Subnet/ipv6Subnet– Optional CIDR prefixes; when omitted, the runtime automatically allocates subnets from the available pool.plugin– Identifies the helper binary that implements the network (default:container-network-vmnet).options– Plugin-specific key-value pairs, such asvariant=reservedfor the vmnet implementation.
The configuration enforces naming constraints and integrates with the container persistence layer, storing network definitions as JSON for durability across system restarts.
Runtime Implementation with vmnet
The default runtime implementation, ReservedVmnetNetwork, bridges container networking to macOS's native vmnet framework. Found in Sources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swift, this class conforms to the NetworkService protocol defined in Sources/Services/Network/Server/NetworkService.swift.
During initialization, the runtime validates that the requested mode is either nat or hostOnly, rejecting unsupported configurations. It then utilizes vmnet reservation APIs (vmnet_network_create, vmnet_network_configuration_set_*) to establish the virtual network interface. The implementation serializes the vmnet_network_ref into XPC messages via serialize_network_ref, enabling secure handoff to client processes.
The NetworkService protocol requires three core operations:
status()– Returns aNetworkStatusobject containing the allocated subnet, gateway address, and optional IPv6 configuration.allocate(hostname:macAddress:session:)– Creates a per-container attachment, assigning IP addresses and MAC addresses to individual containers.lookup(hostname:)– Resolves hostnames to their corresponding network attachments for service discovery.
After calling start(), the runtime exposes network metadata through NetworkStatus, allowing clients to determine gateway addresses and available address ranges.
XPC-Based Client Communication
Client applications interact with network services through NetworkClient, located in Sources/Services/Network/Client/NetworkClient.swift. This client establishes communication with the runtime helper via XPC (Inter-Process Communication), constructing Mach service labels following the pattern <com.apple.container.network>.<plugin>.<id>.
The client API provides three primary operations:
status()– Queries the runtime for current network configuration and health.allocate(hostname:macAddress:on:)– Requests network attachment for a specific container, using an existingXPCClientSessionfor efficient connection reuse.lookup(hostname:)– Performs hostname resolution against the network's allocation table.
All XPC messages route through the NetworkRoutes enum (e.g., .status, .allocate, .lookup) using key constants defined in NetworkKeys. The client decodes JSON responses into typed Swift structures (Attachment, NetworkStatus), providing type-safe access to network metadata.
Command-Line Interface
The container network command family provides user-facing access to the networking API, with implementations residing in Sources/ContainerCommands/Network/. These commands map directly to NetworkClient methods:
container network create <name>– Constructs aNetworkConfigurationfrom flags (--internal,--subnet,--option,--label,--plugin) and invokesNetworkClient.create.container network list– Enumerates all persistent networks viaNetworkClient.list, with--quietfiltering to names only.container network inspect <name>– Retrieves both configuration and runtime status.container network delete <name>– Removes the network configuration and releases runtime resources.container network prune– Identifies and deletes unused networks.
Plugin Architecture and Extensibility
The networking stack employs a plugin-first design that decouples the API from implementation details. The plugin field in NetworkConfiguration determines which helper binary the system launches, with each plugin exposing a Mach service named com.apple.container.network.<plugin>.<id>.
New networking backends can be added by:
- Implementing the
NetworkServiceprotocol. - Registering the service under the standard Mach service label.
- Configuring the container to use the custom plugin name.
The client remains agnostic to implementation specifics, passing only the plugin name to locate the appropriate service. This architecture supports future networking technologies without modifying the core client code.
Practical Examples
Creating a NAT Network
import ContainerResource
import ContainerAPIClient
let config = try NetworkConfiguration(
name: "frontend-network",
mode: .nat,
ipv4Subnet: CIDRv4("10.0.0.0/24"),
plugin: "container-network-vmnet",
options: ["variant": "reserved"]
)
let client = NetworkClient()
let network = try await client.create(configuration: config)
print("Created network:", network.id)
Allocating Container Addresses
let netClient = NetworkClient(id: "frontend-network", plugin: "container-network-vmnet")
let session = netClient.connect()
let (attachment, extra) = try await netClient.allocate(
hostname: "web-server",
macAddress: MACAddress("02:42:ac:11:00:02"),
on: session
)
print("Allocated IP:", attachment.ipv4Address)
CLI Network Management
# Create isolated host-only network
container network create dev-net --internal
# List all networks
container network list
# Inspect network details
container network inspect dev-net
# Remove unused networks
container network prune
Summary
- apple/container provides a layered networking stack for macOS containers with clear separation between configuration, runtime, and client layers.
- NetworkConfiguration in
Sources/ContainerResource/Network/NetworkConfiguration.swiftdefines persistent network properties including NAT and host-only modes. - ReservedVmnetNetwork implements the
NetworkServiceprotocol using macOS vmnet APIs for actual network creation and address allocation. - NetworkClient communicates via XPC to perform operations like
allocate(hostname:macAddress:session:)andlookup(hostname:). - The plugin architecture allows custom networking implementations by conforming to
NetworkServiceand registering Mach services. - The CLI in
Sources/ContainerCommands/Network/provides direct access to create, inspect, and manage container networks.
Frequently Asked Questions
What network modes does apple/container support?
The repository supports two built-in modes defined in Sources/ContainerResource/Network/NetworkMode.swift: NAT (default) and host-only. NAT mode provides outbound network access through macOS's Internet sharing, while host-only creates isolated networks visible only to the host and attached containers.
How does container network allocation work?
The ReservedVmnetNetwork runtime implements allocate(hostname:macAddress:session:) from the NetworkService protocol. When a container starts, the client sends an XPC request to the network helper, which assigns an IP address from the configured subnet and returns an Attachment object containing the IPv4 address, MAC address, and gateway information.
Can I create custom network plugins for apple/container?
Yes. The architecture is plugin-first: implement the NetworkService protocol in Sources/Services/Network/Server/NetworkService.swift, register your service under the Mach service label com.apple.container.network.<plugin>.<id>, and specify your plugin name in the NetworkConfiguration options. The NetworkClient automatically locates and communicates with your service via XPC without requiring changes to the core codebase.
Where are network configurations stored?
Network configurations are persisted as JSON in the container storage layer, managed through NetworkConfiguration in Sources/ContainerResource/Network/NetworkConfiguration.swift. The system validates names using NetworkResource.nameValid(name) and maintains the configuration across system restarts, enabling networks to persist between container engine restarts.
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 →