# How Networks Function Within Container: macOS vmnet Networking Explained

> Discover how container networks function on macOS using the vmnet framework. Learn about IP assignment and isolated virtual networks to understand your container environment better.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: internals
- Published: 2026-06-25

---

**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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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:

```swift
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:)`:

```swift
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:

```bash
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`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Network/NetworkCreate.swift).

### Programmatic Network Creation

Create networks directly in Swift:

```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:

```bash
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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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).