How to Create Custom Networks for macOS 26+ Containers with Apple Container

Apple Container creates isolated custom networks using the vmnet-based container-network-vmnet plugin, accessible via CLI commands or the NetworkClient Swift API.

Apple Container provides a built-in networking stack for macOS 26 and later that abstracts virtual machine networking through the container-network-vmnet plugin. When you execute container system start, the framework initializes a default network automatically, but you can also define completely isolated virtual LANs for specific workloads. Creating custom networks for containers on macOS 26+ ensures traffic segmentation and network isolation between different groups of containers.

Architecture of Custom Container Networks

The XPC Communication Flow

The architecture follows a CLI → XPC → Container-API-Server pattern. When you execute a network command, the CLI parses arguments and builds an XPC message sent to the container-apiserver Mach service (com.apple.container.apiserver). The client implementation resides in Sources/Services/ContainerAPIService/Client/NetworkClient.swift, specifically within the NetworkClient class (lines 24-33) that handles the transport layer.

The container-network-vmnet Plugin

The server delegates network creation to the container-network-vmnet plugin. This plugin creates a vmnet interface, assigns the requested IPv4 and IPv6 CIDR blocks, and registers the network in the server's state. Each network receives its own vmnet interface, ensuring complete traffic isolation between networks. The plugin registration and loading logic is handled by Sources/ContainerPlugin/PluginLoader.swift.

Creating Custom Networks via CLI

Use the container network create command to define isolated networks with specific subnet ranges.

Create a network with custom subnets:


# Create a network called "foo" with explicit IPv4 and IPv6 CIDRs

container network create foo \
    --subnet 192.168.100.0/24 \
    --subnet-v6 fd00:1234::/64

Verify the network exists:

container network list
#> NETWORK  STATE    SUBNET
#> default  running  192.168.64.0/24
#> foo      running  192.168.100.0/24

Attach containers to your custom network:

container run -d --name web --network foo --rm web-test

Clean up resources:

container stop web
container network delete foo

Programmatic Network Management with NetworkClient

For Swift applications, interact directly with the XPC service using NetworkClient from Sources/Services/ContainerAPIService/Client/NetworkClient.swift.

import ContainerResource
import ContainerPlugin

let client = NetworkClient()

// Define a custom network configuration
let config = NetworkConfiguration(
    id: "my-custom-net",
    name: "my-custom-net",
    subnet: "192.168.200.0/24",
    subnetv6: "fd00:abcd::/64",
    internal: false,
    labels: [:],
    options: [:],
    plugin: "container-network-vmnet"
)

// Create the network using the create method (lines 67-84)
let network = try await client.create(configuration: config)
print("Created network \(network.id) with IPv4 \(network.subnet)")

// List all networks using the list method (lines 91-104)
let all = try await client.list()
print("Current networks: \(all.map(\.id))")

// Delete the network when done
try await client.delete(id: config.id)

The create method sends a .networkCreate route request, while list invokes the networkList XPC route. The delete method (lines 21-33) submits a networkDelete request after verifying no containers remain attached.

Network Lifecycle and Isolation

Persistent State and Pruning

Networks persist while the API server runs. You can remove unused networks using container network delete <name>, which executes the delete method in NetworkClient.swift after validating zero container attachments. To bulk-remove unused networks, use container network prune, which preserves the built-in default network while deleting all unattached custom networks, as documented in docs/command-reference.md.

Traffic Isolation Guarantees

Each custom network operates as a completely isolated virtual LAN. Containers attached to one network cannot see traffic on any other network, including the built-in default network. This isolation is enforced at the vmnet interface level, as described in docs/how-to.md under the "Create and use a separate isolated network" section.

Summary

  • Apple Container uses the container-network-vmnet plugin to create vmnet-based networks on macOS 26+.
  • The NetworkClient class in Sources/Services/ContainerAPIService/Client/NetworkClient.swift implements XPC communication with the container-apiserver Mach service.
  • Custom networks support explicit IPv4 and IPv6 CIDR assignment via CLI flags or the NetworkConfiguration struct.
  • Each network receives a dedicated vmnet interface, ensuring complete traffic isolation between container groups.
  • Networks persist until explicitly deleted or pruned, with the default network remaining protected during cleanup operations.

Frequently Asked Questions

What is the default network created by Apple Container?

When you run container system start, the framework automatically creates a network named default with a predefined subnet (typically 192.168.64.0/24). This network is initialized in NetworkClient.swift (lines 43-45) and is protected from pruning operations, serving as the primary network for containers that do not specify a --network flag.

Can containers communicate across different custom networks?

No. Containers attached to different networks are completely isolated. The container-network-vmnet plugin creates separate vmnet interfaces for each network, preventing cross-network traffic at the virtualization layer. This design follows the standard container networking model where explicit bridge or routing configuration is required for inter-network communication.

How do I specify which network plugin to use when creating a network?

By default, Apple Container uses the container-network-vmnet plugin. When using the Swift API, set the plugin parameter in NetworkConfiguration to "container-network-vmnet". The CLI currently uses this plugin automatically, with plugin selection handled internally by the PluginLoader in Sources/ContainerPlugin/PluginLoader.swift.

What happens if I try to delete a network that still has running containers?

The deletion operation fails. The NetworkClient.delete method (implemented in NetworkClient.swift lines 21-33) validates that no containers are attached to the network before submitting the networkDelete XPC request to the server. You must stop and remove all attached containers before the network can be deleted.

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 →