How to Configure Network Isolation and Custom Subnets for Containers in Apple Container
Use the container network create command with the --internal flag for isolation and --subnet/--subnet-v6 flags to specify custom CIDR ranges, which are validated by the DefaultNetworkService and configured via the macOS vmnet framework.
The apple/container repository provides a robust networking stack that allows you to create isolated container networks with precise IP addressing control. When you need to configure network isolation and custom subnets for containers, the platform exposes a dedicated CLI sub-command that translates high-level flags into low-level VM-net interfaces. This implementation leverages the macOS vmnet framework to enforce traffic boundaries while supporting both IPv4 and IPv6 custom address ranges.
Understanding the Network Architecture
The networking system consists of several coordinated components that handle everything from CLI flag parsing to kernel-level network interface creation.
Core Components
Application.NetworkCreate– The CLI entry point inSources/ContainerCommands/Network/NetworkCreate.swiftthat parses user flags like--subnet,--subnet-v6, and--internalto build a configuration object.NetworkConfiguration– The data model defined inSources/ContainerResource/Network/NetworkConfiguration.swiftthat stores CIDR strings and converts them intoCIDRv4/CIDRv6objects for validation.NetworkClient– The API client inSources/Services/ContainerAPIService/Client/NetworkClient.swiftthat transmits the configuration via aPOST /networksrequest to the daemon.DefaultNetworkService– The server-side implementation inSources/Services/Network/Server/DefaultNetworkService.swiftthat validates subnets against existing networks and prevents overlapping address space.ReservedVmnetNetwork– The low-level wrapper inSources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swiftthat callsvmnet_network_configuration_set_ipv4_subnetto program the actual interface.
Creating an Isolated Network with Custom Subnets
To achieve true network isolation, you must specify the --internal flag, which sets the NetworkMode to hostOnly. This prevents NAT and blocks external internet access, restricting communication to the host and other containers on the same network.
Step-by-Step CLI Usage
The container network create command accepts specific CIDR notation for both IPv4 and IPv6 ranges. The DefaultNetworkService validates these ranges using the validateSubnet method to ensure no overlap with existing networks before creating the interface.
# Create an isolated network with custom IPv4 and IPv6 subnets
container network create \
--internal \
--subnet 10.42.0.0/16 \
--subnet-v6 fd00:1234::/48 \
isolated-net
This command triggers the following sequence:
- CLI Parsing:
NetworkCreate.swift(lines 44-55) parses--internalintoNetworkMode.hostOnlyand converts the subnet strings intoCIDRv4/CIDRv6objects. - API Transmission:
NetworkClientsends theNetworkConfigurationto the server viaPOST /networks. - Validation:
DefaultNetworkService(lines 36-44) checks for subnet collisions and creates either aReservedVmnetNetwork(if you specified a subnet) or anAllocationOnlyVmnetNetwork(for automatic allocation). - Interface Creation:
ReservedVmnetNetwork(lines 122-140) configures the macOSvmnetinterface with your exact IPv4 CIDR usingvmnet_network_configuration_set_ipv4_subnet.
Attaching Containers to the Isolated Network
Once created, attach containers using the network name. Containers on this network receive IP addresses from your specified CIDR range and cannot reach external networks.
container run \
--network isolated-net \
nginx:latest
Implementation Details
CLI Flag Processing
In Sources/ContainerCommands/Network/NetworkCreate.swift, the NetworkCreate command handles the --subnet and --internal flags. The --internal flag specifically sets the network mode to .hostOnly, which disables NAT and creates an isolated segment. The subnet values are validated as proper CIDR notation before being packaged into the NetworkConfiguration struct.
Configuration Model
The NetworkConfiguration struct in Sources/ContainerResource/Network/NetworkConfiguration.swift (lines 35-55) holds the optional CIDR fields. This model determines whether the network operates in nat mode (default) or hostOnly mode (isolated), and stores the NetworkMode enum value defined in Sources/ContainerResource/Network/NetworkMode.swift.
Server-Side Subnet Validation
The DefaultNetworkService in Sources/Services/Network/Server/DefaultNetworkService.swift performs critical validation before interface creation. The service maintains a registry of existing networks and uses the validateSubnet method to detect overlapping IPv4 ranges. If you omit the --subnet flag, the service automatically allocates a non-overlapping subnet; if you specify one, it creates a ReservedVmnetNetwork with your exact range.
Low-Level VM-net Configuration
The actual network isolation is enforced by the macOS vmnet framework. In Sources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swift, the initialization code calls vmnet_network_configuration_set_ipv4_subnet to program the kernel-level interface with your custom CIDR. This ensures that the DHCP-style allocator built into vmnet only hands out addresses within your specified range to attached containers.
Summary
- Use
container network create --internalto enableNetworkMode.hostOnlyand achieve true network isolation from external traffic. - Specify
--subnetand--subnet-v6to define custom CIDR ranges; theDefaultNetworkServicevalidates these against existing networks to prevent collisions. - The architecture flows from CLI (
NetworkCreate.swift) to API client (NetworkClient.swift) to server validation (DefaultNetworkService.swift) to kernel interface (ReservedVmnetNetwork.swift). - Isolated networks restrict container communication to the host and other containers on the same network, with IP assignment strictly limited to your configured subnets.
Frequently Asked Questions
What is the difference between --internal and omitting the flag?
When you use --internal, the NetworkConfiguration sets NetworkMode to hostOnly, which creates an isolated network without NAT. Containers can only communicate with the host and other containers on the same network. Without the flag, the network uses nat mode, allowing containers to reach external networks through the host's internet connection.
How does the system prevent subnet collisions?
The DefaultNetworkService in Sources/Services/Network/Server/DefaultNetworkService.swift implements the validateSubnet method, which checks your requested CIDR against all existing networks. If an overlap is detected, the API returns an error before creating the ReservedVmnetNetwork interface, preventing routing conflicts at the macOS vmnet level.
Can I use IPv6 automatic allocation like IPv4?
Currently, automatic allocation is fully implemented for IPv4 only. For IPv6, you must explicitly provide a CIDR using the --subnet-v6 flag. The server validates that the IPv6 prefix does not overlap with existing networks, but it will not generate an IPv6 range automatically if you omit the flag.
What happens if I don't specify a subnet?
If you omit the --subnet flag, the DefaultNetworkService creates an AllocationOnlyVmnetNetwork instead of a ReservedVmnetNetwork. This automatically selects a non-overlapping IPv4 CIDR from the available pool and configures the vmnet interface without reserving a specific range, simplifying network creation when precise IP control is not required.
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 →