How Networks Function Within Container: macOS vmnet Networking Explained

Container networking leverages the macOS vmnet framework and XPC helpers to create isolated virtual networks, automatically assigning IP addresses to containers through the container-network-vmnet helper.

The apple/container repository implements a sophisticated networking stack that bridges macOS virtualization capabilities with container workloads. Understanding how networks function within Container requires examining the interaction between the vmnet framework, XPC-based helper services, and the Swift APIs exposed to users. This architecture enables seamless network isolation while maintaining the performance characteristics of native macOS virtualization.

Core Architecture: The vmnet Framework and XPC Helpers

When container system start executes, the container-apiserver launch agent initializes three critical helper processes that orchestrate container lifecycle and networking.

The Three Core Services

The system relies on distinct helpers for specialized functions:

  • container-core-images – Manages container images and layer storage
  • container-network-vmnet – Implements the virtual network interface using the vmnet framework
  • container-runtime-linux – Executes and monitors container processes

The network helper creates a vmnet network named default that automatically attaches to every container unless overridden by specific configuration.

Network Isolation

Each network operates in complete isolation from others. Containers sharing the same network can communicate directly, while cross-network traffic is prohibited. This isolation is enforced at the vmnet framework level.

Note: On macOS 15, the vmnet framework supports only a single network, which restricts container network commands on that version.

Network Configuration and Definition

Networks are defined by the NetworkConfiguration struct located in Sources/ContainerResource/Network/NetworkConfiguration.swift.

Configuration Structure

The struct encapsulates:

  • Name – Unique network identifier
  • Mode – Either nat or hostOnly
  • Subnets – Optional IPv4 (CIDRv4) and IPv6 (CIDRv6) specifications
  • Labels – Metadata via ResourceLabels
  • Plugin – Always container-network-vmnet for the default implementation
  • Options – Plugin-specific key-value pairs

Validation and Serialization

The NetworkConfiguration validates network names and serializes to JSON for transmission via XPC. This ensures type safety across the client-helper boundary defined in NetworkRoutes and NetworkKeys.

The NetworkClient: XPC Communication Layer

The NetworkClient class in Sources/Services/Network/Client/NetworkClient.swift provides the Swift interface for network operations.

Establishing Persistent Connections

The connect() method opens a persistent XPC session that must remain active for the duration of any network allocations. Closing this session automatically releases all associated IP allocations.

Allocating Network Attachments

The allocate(hostname:macAddress:on:) method requests IP and MAC address assignment:

import ContainerNetworkClient
import ContainerXPC

let client = NetworkClient(id: "foo", plugin: "container-network-vmnet")
let session = client.connect()
let (attachment, _) = try await client.allocate(
    hostname: "my-web-server.test.",
    macAddress: MACAddress("02:42:ac:11:00:02"),
    on: session
)

print("Container received IP: \(attachment.address)")

The helper returns an Attachment value describing the network interface configuration.

Looking Up Existing Attachments

Query existing allocations using lookup(hostname:):

let client = NetworkClient(id: "foo", plugin: "container-network-vmnet")
if let attachment = try await client.lookup(hostname: "my-web-server.test.") {
    print("Found IP: \(attachment.address)")
}

CLI Integration and Usage

The container network subcommands provide thin wrappers over the NetworkClient API, handling argument parsing and configuration building.

Creating Custom Networks

Create isolated networks with custom subnets and labels:

container network create foo \
    --subnet 192.168.100.0/24 \
    --subnet-v6 fd00:1234::/64 \
    --label env=dev \
    --option foo=bar

This command parses options into a NetworkConfiguration and invokes NetworkClient().create(configuration:) behind the scenes. The implementation resides in Sources/ContainerCommands/Network/NetworkCreate.swift.

Programmatic Network Creation

Create networks directly in Swift:

import ContainerResource
import ContainerNetworkClient

let labels = try ResourceLabels(["env": "dev"])
let options = ["foo": "bar"]

let config = try NetworkConfiguration(
    name: "foo",
    mode: .nat,
    ipv4Subnet: CIDRv4("192.168.100.0/24"),
    ipv6Subnet: CIDRv6("fd00:1234::/64"),
    labels: labels,
    plugin: "container-network-vmnet",
    options: options
)

let client = NetworkClient()
let network = try await client.create(configuration: config)
print("Created network with ID: \(network.id)")

Inspecting Network State

Retrieve network details in JSON format:

container network inspect foo --format json

Runtime Behavior: IP Allocation and Lifecycle

When a container starts, the runtime helper passes the network name to container-network-vmnet via XPC messages. The helper then:

  1. Allocates an IP address from the network's CIDR range
  2. Updates the container's /sys/class/net/eth0 interface data
  3. Records the attachment in internal state

The allocation persists until the XPC session closes (e.g., when the container stops), at which point the helper automatically releases the IP address back to the pool.

The NetworkVmnetHelper.swift file in Sources/Plugins/NetworkVmnet/ serves as the entry point for these XPC operations, handling the low-level vmnet framework interactions.

Summary

  • Container networking relies on the macOS vmnet framework and the container-network-vmnet XPC helper for virtual network implementation
  • NetworkClient in Sources/Services/Network/Client/NetworkClient.swift manages persistent XPC connections and IP allocation through allocate() and lookup() methods
  • NetworkConfiguration defines network properties including mode (nat or hostOnly), subnets, and labels, validated in Sources/ContainerResource/Network/NetworkConfiguration.swift
  • Automatic cleanup occurs when XPC sessions close, releasing IP allocations without manual intervention
  • macOS 15 limitation restricts the framework to a single network, disabling multiple network creation on that version

Frequently Asked Questions

How does Container handle IP address assignment?

Container uses the container-network-vmnet helper to allocate IP addresses dynamically from the network's defined CIDR range. When a container starts, the runtime requests an allocation via XPC, receiving an Attachment object containing the assigned IP and interface configuration. The helper updates the container's network interface files directly and automatically releases the address when the container stops and the XPC session terminates.

Can I use custom subnets when creating networks?

Yes. The NetworkConfiguration struct accepts optional ipv4Subnet and ipv6Subnet parameters using CIDRv4 and CIDRv6 types. You can specify these via the CLI using --subnet and --subnet-v6 flags, or programmatically when initializing NetworkConfiguration in Swift. The helper validates these ranges before allocation.

Why are container network commands unavailable on macOS 15?

The vmnet framework on macOS 15 supports only a single virtual network interface. Since Container's architecture expects the ability to create multiple isolated networks, the container network subcommands are disabled on this version to prevent configuration errors. Containers still receive network connectivity through the automatically created default network.

How do containers communicate across different networks?

Containers on different networks cannot communicate directly. The vmnet framework enforces isolation between networks at the virtualization layer. To enable communication, containers must reside on the same network, or traffic must route through a bridge container that attaches to multiple networks (though this requires specific configuration not available on macOS 15 due to single-network limitations).

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →