How to Run a Container on a Specific Network Using Apple Container
To run a container on a specific network, first create an isolated network with container network create <name>, then attach the container using the --network <name> flag when calling container run.
The Apple Container framework implements vmnet-based virtual networking to isolate container traffic. When the container system initializes, it automatically provisions a default network named default using the CIDR 192.168.64.0/24. To route a container through a different subnet or bridge, you must explicitly create that network namespace and reference it during container creation. This guide walks through the CLI commands and the underlying implementation in apple/container source code.
Understanding the vmnet Architecture
Under the hood, the CLI communicates network requirements to a runtime service via XPC. When you specify a network, RuntimeService.swift (lines 172–190) constructs a NetworkBootstrapInfo struct and passes it to the RuntimeClient. The runtime then instantiates a ContainerNetworkClient that interfaces with the container-network-vmnet helper. This helper creates a vmnet_network_ref (implemented in Sources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swift, lines 57–158) to allocate the virtual interface, returning the assigned IP address, gateway, and MAC address to the container’s sandbox.
Creating an Isolated Network
Before attaching a container, you must provision the network. Use the container network create command to establish a new vmnet-based subnet.
# Create a basic network with auto-allocated subnet (192.168.65.0/24 by default)
container network create foo
For environments requiring specific addressing, define custom IPv4 and IPv6 ranges. According to ReservedVmnetNetwork.swift (lines 136–151), the service validates and stores these subnets in the network-service structs:
# Create a network with explicit subnets
container network create bar \
--subnet 192.168.100.0/24 \
--subnet-v6 fd00:1234::/64
Verify the creation by listing available networks:
container network list
This outputs the network state and assigned CIDR blocks:
NETWORK STATE SUBNET
default running 192.168.64.0/24
foo running 192.168.65.0/24
bar running 192.168.100.0/24
Running a Container on a Specific Network
Once the network exists, attach containers to it using the --network flag. The RuntimeService.swift file (lines 172–190) parses this flag into a NetworkAttachment struct that includes the network name and optional interface parameters.
# Run a detached container attached to the "foo" network
container run -d --name web1 \
--network foo \
--rm ghcr.io/apple/container-demo:web-test
The container receives an IP address from the specified subnet (e.g., 192.168.65.2/24) and uses the network’s gateway for external routing. Inspect the assigned configuration:
container inspect web1 | jq '.networks[0]'
Example output:
{
"address": "192.168.65.2/24",
"gateway": "192.168.65.1",
"hostname": "web1.test.",
"network": "foo"
}
Configuring MAC Addresses and MTU
You can fine-tune the container’s network interface by appending parameters to the --network flag. Separate each option with a comma:
# Run with a deterministic MAC address
container run --network default,mac=02:42:ac:11:00:02 \
--rm alpine:latest \
cat /sys/class/net/eth0/address
Available parameters:
- mac= – Sets a specific MAC address (e.g.,
mac=02:42:ac:11:00:02) - mtu= – Specifies the maximum transmission unit in bytes (e.g.,
mtu=1500)
Publishing Ports on Specific Networks
When exposing container services to the host, the -p flag binds to the first network specified in --network. Traffic routes through that specific subnet’s bridge:
# Publish host port 8080 to container port 8000 via the "foo" network
container run -d --name api \
--network foo \
-p 127.0.0.1:8080:8000 \
ghcr.io/apple/container-demo:web-test
Requests to http://127.0.0.1:8080 traverse the foo network to reach the container at its assigned IP.
Platform Limitations on macOS
The networking capabilities depend on the host operating system version. In macOS 15, the vmnet framework supports only a single active network, meaning the --network flag will error if you attempt to attach to a second custom network while the default network is active. macOS 26+ removes this restriction, allowing full multi-network isolation where containers can connect to distinct subnets simultaneously.
Cleaning Up Networks
Delete a network only after detaching all running containers. The NetworkService tears down the vmnet_network_ref and frees the address space:
container network delete foo
Attempting to delete an active network returns an error until all attached containers are stopped or removed.
Summary
- Create networks first – Use
container network createto provision vmnet subnets before running containers. - Attach with
--network– Pass the network name tocontainer runorcontainer createto assign the container to a specific subnet. - Customize interfaces – Append
mac=andmtu=to the network flag for deterministic hardware addresses. - Check platform support – Multi-network features require macOS 26+; macOS 15 is limited to the default network.
- Reference implementation – Core logic resides in
RuntimeService.swift(XPC messaging) andReservedVmnetNetwork.swift(vmnet allocation).
Frequently Asked Questions
Can I attach a running container to multiple networks?
No, each container instance binds to a single network at creation time. The NetworkBootstrapInfo struct passed via XPC in RuntimeService.swift accepts one network configuration per container. To change networks, you must stop the container and recreate it with a different --network flag.
How do I configure a static IP address for a container?
The Apple Container implementation assigns IPs dynamically via the vmnet framework. While you can specify a custom MAC address using --network foo,mac=..., static IP assignment is not exposed in the current CLI. The IP allocation occurs inside ReservedVmnetNetwork.swift (lines 57–158) when the vmnet interface is created.
Why does the --network flag fail on macOS 15?
macOS 15’s vmnet framework only supports a single active network interface. If the default network is running, attempting to specify --network <custom> triggers an error because the system cannot provision additional vmnet_network_ref instances. Upgrade to macOS 26+ for multi-network support, or stop all containers and delete the default network before using custom networks.
Where does the network configuration persist?
Network definitions are managed by the NetworkService daemon and stored in the container system’s data directory. You can inspect the current state using container network inspect <name>, which queries the vmnet helper for IPv4/IPv6 subnets, gateway information, and attached container IDs as implemented in Sources/Services/Network/Server/NetworkService.swift.
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 →