How to Manage Multiple Networks in Container on macOS Using NetworkCommand
The NetworkCommand suite in Apple's Container project enables you to create, inspect, and attach macOS containers to multiple isolated virtual networks using the vmnet framework, with each network definition persisted as a NetworkResource in the system configuration.
The Apple Container project implements its networking stack on macOS through the container-network-vmnet plugin. Understanding how to manage multiple networks in container on macOS using NetworkCommand allows you to segment traffic between frontend and backend services, configure custom subnets, and maintain persistent network topologies that survive daemon restarts. The CLI forwards all network operations to the Container API Service (/container/v1/network), which translates requests into calls to the underlying vmnet framework via the Networks harness and service layers.
Understanding the NetworkCommand Architecture
The NetworkCommand struct in Sources/ContainerCommands/Network/NetworkCommand.swift serves as the root command that registers five sub-commands: NetworkCreate, NetworkDelete, NetworkList, NetworkInspect, and NetworkPrune. Each command builds an appropriate request payload and communicates with the daemon through the ContainerAPIClient over gRPC.
When you invoke container network create, the CLI constructs a NetworkConfiguration object (Sources/ContainerResource/Network/NetworkConfiguration.swift) containing your specified subnet, gateway, MTU, and labels. The daemon persists this as a NetworkResource (Sources/ContainerResource/Network/NetworkResource.swift) via ContainerSystemConfig.swift, ensuring your network definitions survive daemon restarts. The actual virtual switch creation happens in the container-network-vmnet plugin (Sources/Plugins/NetworkVmnet/NetworkVmnetHelper.swift), which exposes Mach services such as com.apple.container.network.hydra.
Creating Isolated Network Segments
Create independent networks with distinct subnets to isolate container traffic. The CLI validates name uniqueness, IPAM settings, and driver options before forwarding to the plugin.
Define a frontend network with specific addressing:
container network create \
--label purpose=frontend \
--subnet 10.1.0.0/24 \
--gateway 10.1.0.1 \
--mtu 1500 \
frontend
Define a backend network with custom MAC prefixing:
container network create \
--label purpose=backend \
--subnet 10.2.0.0/24 \
--gateway 10.2.0.1 \
--mac-prefix 02:42:ac \
backend
Implementation detail: The NetworkCreate struct in Sources/ContainerCommands/Network/NetworkCreate.swift converts these flags into a NetworkConfiguration instance, which the daemon stores via ContainerSystemConfig.
Listing and Inspecting Networks
View all defined networks sorted by name:
container network ls
Behind the scenes: The NetworkList command (Sources/ContainerCommands/Network/NetworkList.swift) queries the NetworksHarness for the current snapshot of NetworkResource objects.
Retrieve detailed JSON output for a specific network:
container network inspect frontend
The output includes fields such as ID, Name, Subnet, Gateway, MTU, and labels. This maps to the NetworkInspectOutput structure used in integration tests (Tests/IntegrationTests/Utilities/ContainerFixture+NetworkHelpers.swift).
Attaching Containers to Multiple Networks
Attach a single container to multiple networks simultaneously using comma-separated values:
container run -d \
--name web \
--network frontend,backend \
nginx:stable
What happens internally: The CLI expands the comma-separated list and builds a ContainerResource.Attachment array (see ContainerFixture+ContainerHelpers.swift in integration tests). The daemon creates a NetworkStatus entry for each attachment, exposing the assigned MAC address, IP address, and hostname to the container runtime. The container receives two network interfaces—for example, 10.1.0.5 on frontend and 10.2.0.5 on backend.
Verify the dual attachment from within the container:
container exec web ip addr show
You will see two ethX interfaces, each displaying the IP and MAC allocated by their respective NetworkStatus entries.
Removing and Pruning Networks
The NetworkDelete command (Sources/ContainerCommands/Network/NetworkDelete.swift) prevents removal of networks currently referenced by running containers.
Attempting to delete an attached network fails:
container network delete frontend
# Error: network is in use
First stop and remove the container, then delete the network:
container stop web && container rm web
container network delete frontend
Remove all unused networks with a single command:
container network prune
The NetworkPrune implementation (Sources/ContainerCommands/Network/NetworkPrune.swift) queries the ContainerSystemConfig for networks with no active attachments and removes them from the persistent store.
Summary
NetworkCommandserves as the root CLI entry point for all network operations, delegating toNetworkCreate,NetworkDelete,NetworkList,NetworkInspect, andNetworkPrune.- Networks are defined as
NetworkResourceobjects stored inContainerSystemConfig, ensuring persistence across daemon restarts. - The
container-network-vmnetplugin implements the actual virtual networking using the vmnet framework and Mach services. - Containers can attach to multiple networks simultaneously, receiving separate IP addresses and MAC addresses for each network interface.
- The CLI enforces safety checks by preventing deletion of networks with active container attachments.
Frequently Asked Questions
Can a macOS container attach to multiple networks at the same time?
Yes. The container run command accepts comma-separated network names via the --network flag. The CLI constructs a ContainerResource.Attachment array for each network, and the daemon creates corresponding NetworkStatus entries that provide separate IP addresses and MAC addresses for each network interface inside the container.
Where does the Container daemon store network configurations?
Network definitions persist in ContainerSystemConfig (Sources/ContainerPersistence/ContainerSystemConfig.swift). This storage mechanism maintains the list of NetworkResource objects and their state across daemon restarts, ensuring that your isolated network segments remain available after system reboots.
Which component implements the actual virtual networking on macOS?
The container-network-vmnet plugin (Sources/Plugins/NetworkVmnet/NetworkVmnetHelper.swift) implements the networking layer by interfacing with Apple's vmnet framework. It creates virtual switches (VMnet) and exposes Mach services such as com.apple.container.network.hydra to handle packet forwarding between containers and the host.
Why does container network delete report an error for some networks?
The deletion command checks for active references in the ContainerSystemConfig. If any container maintains a NetworkStatus entry for the target network, the NetworkDelete command aborts with an error to prevent accidental disruption of running workloads. You must stop and remove all attached containers before the network can be safely 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →