How to Configure Custom Networks for Containers in Apple Container

To configure custom networks for containers, edit ~/.config/container/config.toml to set default subnets, use container network create with --subnet flags for specific networks, and attach containers with container run --network <name>.

The apple/container project implements container networking on top of the vmnet framework, exposing both a command-line interface and a Swift-level API for managing isolated network segments. Network configuration persists in a TOML-based system config file and supports custom IPv4/IPv6 CIDR blocks, MAC address assignment, and MTU customization.

Understanding Container Network Architecture

The networking subsystem relies on several core concepts defined in the source code.

Default and Reserved Networks

The system maintains two special network identifiers hardcoded in Sources/Services/ContainerAPIService/Client/NetworkClient.swift:

  • default – The automatic network created on first use (NetworkClient.defaultNetworkName = "default"). This network cannot be deleted.
  • none – A reserved identifier (NetworkClient.noNetworkName = "none") that instructs the runtime to run a container without any network attachment.

Configuration File Structure

The NetworkConfig struct in Sources/ContainerPersistence/ContainerSystemConfig.swift maps the TOML schema to runtime objects. The [network] section accepts optional subnet and subnetv6 entries that supply defaults for newly created networks.

Setting Global Network Defaults

You can establish system-wide defaults by modifying ~/.config/container/config.toml. These values apply only when creating networks without explicit subnet flags.

[network]
subnet = "192.168.100.1/24"      # IPv4 CIDR

subnetv6 = "fd00:abcd::/64"     # IPv6 CIDR

The ContainerSystemConfig.swift file parses these values at startup, injecting them into the NetworkConfig struct used by the XPC service.

Creating and Managing Custom Networks

CLI Network Creation

Use the container network create command to establish isolated vmnet networks. The CLI supports custom subnets and internal-only isolation.


# Basic network named "foo"

container network create foo

# With custom IPv4 and IPv6 subnets

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

The command serializes the configuration and sends it to the daemon, which returns a NetworkResource representing the created segment.

Swift API Network Creation

For programmatic control, instantiate NetworkClient and invoke create(configuration:). This method encodes the configuration as JSON and transmits it via XPC to the server.

import ContainerPlugin
import ContainerResource
import ContainerXPC

let client = NetworkClient()
let config = NetworkConfiguration(
    id: "foo",
    subnet: CIDRv4("192.168.100.0/24"),
    subnetv6: CIDRv6("fd00:1234::/64")
)
Task {
    do {
        let resource = try await client.create(configuration: config)
        print("Created network: \(resource.id)")
    } catch {
        print("Failed: \(error)")
    }
}

The implementation in Sources/Services/ContainerAPIService/Client/NetworkClient.swift (lines 67-88) handles the encoding and XPC routing through the networkCreate route.

Attaching Containers to Networks

Attach containers to your custom network using the --network flag with container run or container create. You can optionally specify a MAC address or MTU inline.

container run -d --name my-web \
    --network foo,mac=02:42:ac:11:00:02 \
    nginx:latest

The container receives an IP address from the chosen network's subnet. Use container ls to verify the assigned address. As documented in docs/command-reference.md, the --network flag accepts comma-separated options for fine-grained control.

Cleaning Up Networks

Remove unused networks with the delete command. Networks can only be deleted when no containers remain attached.

container network delete foo

Note that the built-in default network is protected and will reject deletion attempts, as enforced by the defaultNetworkName constant in NetworkClient.swift.

Summary

  • Global defaults are configured in ~/.config/container/config.toml under the [network] section, parsed by ContainerSystemConfig.swift.
  • Custom networks are created via container network create with --subnet and --subnet-v6 flags, or programmatically via NetworkClient.create(configuration:).
  • Container attachment uses container run --network <name> with optional MAC/MTU parameters.
  • Reserved networks include default (required, auto-created) and none (isolated mode).
  • Implementation relies on the vmnet framework with XPC communication defined in Sources/Services/ContainerAPIService/Client/NetworkClient.swift.

Frequently Asked Questions

How do I run a container without any network access?

Use the reserved none network name. According to NetworkClient.noNetworkName in NetworkClient.swift, passing --network none to container run instructs the runtime to skip network interface creation entirely, resulting in an isolated container with no network connectivity.

Can I modify the subnet of the default network after creation?

No. The default network (NetworkClient.defaultNetworkName = "default") is created automatically on first use and its configuration is fixed. To use custom subnets, create a new user-defined network with container network create and specify your desired CIDR blocks with --subnet flags.

What happens if I don't specify subnets when creating a network?

The system falls back to values defined in ~/.config/container/config.toml. If the [network] section is absent or incomplete, the vmnet framework assigns default values automatically. The NetworkConfig struct in ContainerSystemConfig.swift handles this resolution logic.

Is the Swift API available to third-party applications?

Yes. The NetworkClient class in Sources/Services/ContainerAPIService/Client/NetworkClient.swift is part of the public framework. It exposes asynchronous methods like create(configuration:) that encode NetworkConfiguration objects as JSON and communicate with the XPC service, allowing external Swift applications to manage container networks programmatically.

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 →