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

> Learn to create custom networks for macOS containers with apple/container. Utilize the vmnet-based container-network-vmnet plugin via CLI or Swift API for isolated networking.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-06-23

---

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

```bash

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

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

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

```

Clean up resources:

```bash
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`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/NetworkClient.swift).

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