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.tomlunder the[network]section, parsed byContainerSystemConfig.swift. - Custom networks are created via
container network createwith--subnetand--subnet-v6flags, or programmatically viaNetworkClient.create(configuration:). - Container attachment uses
container run --network <name>with optional MAC/MTU parameters. - Reserved networks include
default(required, auto-created) andnone(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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →