How to Create an Isolated Container Network with Custom Subnets
Use the container network create command with the --internal and --subnet flags to define a private, isolated network with a specific CIDR range that prevents overlap with existing networks.
The apple/container CLI provides a dedicated network sub-command for defining private container networks with precise IP addressing requirements. When you need to isolate containers from external networks while controlling their IP allocation, the tool constructs a NetworkConfiguration object and processes it through the NetworkClient to the Container API server, which validates the requested subnets and configures the underlying VM-net interface.
Understanding the Network Architecture
Creating an isolated container network with custom subnets involves a coordinated flow between the CLI, API client, and server-side network service. The architecture ensures that your specified CIDR ranges are validated against existing networks before the system reserves the address space.
In Sources/ContainerCommands/Network/NetworkCreate.swift, the Application.NetworkCreate struct parses user-provided flags like --subnet and --internal to build a configuration object. This NetworkConfiguration model, defined in Sources/ContainerResource/Network/NetworkConfiguration.swift, holds the optional CIDRv4 and CIDRv6 values alongside the network mode selection.
The NetworkClient transmits this configuration via a POST /networks request to the Container API server. On the server side, Sources/Services/Network/Server/DefaultNetworkService.swift implements the DefaultNetworkService class, which validates that requested subnets do not overlap with existing networks using the validateSubnet method. For custom subnets, the service creates a ReservedVmnetNetwork instance that configures the exact IPv4 CIDR you specified through the macOS vmnet framework.
Creating an Isolated Network with Custom Subnets
Step 1: Define the Network Configuration via CLI
The CLI entry point in NetworkCreate.swift processes your command-line arguments to construct the network definition. When you specify --internal, the system sets the NetworkMode to hostOnly, creating an isolated network that prevents containers from reaching external networks or the internet.
The --subnet flag accepts a CIDR notation (e.g., 10.42.0.0/16) that the CLI parses into the NetworkConfiguration structure. If you require IPv6 addressing, use --subnet-v6 with an appropriate prefix like fd00:1234::/48.
Step 2: Server-Side Validation and Allocation
Once the NetworkClient submits the configuration, the DefaultNetworkService performs collision detection. It checks your requested IPv4 subnet against all existing networks to ensure no overlap exists. This validation occurs before any system resources are allocated.
If you omit the --subnet flag, the service automatically allocates a non-overlapping subnet from the available pool. However, specifying a custom subnet triggers the creation of a ReservedVmnetNetwork rather than an AllocationOnlyVmnetNetwork, ensuring the system reserves your exact CIDR requirements.
Step 3: VM-Net Interface Initialization
In Sources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swift, the service calls vmnet_network_configuration_set_ipv4_subnet to configure the macOS VM-net framework with your specific subnet. This low-level configuration enforces the isolation boundaries while respecting your custom IP address range.
The server returns the newly created network's UUID, which the CLI prints to stdout for use in subsequent container attachment commands.
Complete CLI Examples
Create a completely isolated network with custom IPv4 and IPv6 subnets:
# Create an isolated network with specific CIDR ranges
container network create \
--internal \
--subnet 10.42.0.0/16 \
--subnet-v6 fd00:1234::/48 \
isolated-net
The command outputs the network UUID:
4e2d5a1b-c0f9-4c1a-a3e7-7e9f8c1d2b57
Attach a container to your isolated network:
container run \
--network isolated-net \
-p 8080:80 \
nginx:latest
Configuration Flags Explained
-internal: ForcesNetworkMode.hostOnly, creating an isolated network where containers can only communicate with each other and the host, blocking external internet access.--subnet <CIDR>: Specifies the IPv4 address range (e.g.,192.168.100.0/24). The service validates this against existing networks to prevent overlap.--subnet-v6 <CIDR>: Defines the IPv6 prefix for the network. Unlike IPv4, IPv6 subnets must be explicitly provided if required; the service rejects overlapping prefixes.<network-name>: The human-readable identifier used when attaching containers via the--networkflag in run commands.
Summary
- Use
container network createwith--internalto achieve true network isolation viaNetworkMode.hostOnly. - Specify custom subnets with
--subnetand--subnet-v6to control IP allocation within your container network. - The
DefaultNetworkServicevalidates all custom subnets against existing networks to prevent CIDR collisions before creating the VM-net interface. - Source files
NetworkCreate.swift,NetworkConfiguration.swift, andReservedVmnetNetwork.swifthandle the complete pipeline from CLI parsing to low-level network configuration. - Isolated networks restrict containers to host-only communication while custom subnets determine the available IP address ranges for attached containers.
Frequently Asked Questions
How does the container tool prevent subnet overlap?
The DefaultNetworkService in Sources/Services/Network/Server/DefaultNetworkService.swift implements a validateSubnet method that checks your requested CIDR against all existing networks before allocation. If the requested range overlaps with an existing network, the API returns an error and the creation fails.
Can I create an isolated network without specifying a subnet?
Yes. If you omit the --subnet flag, the system automatically allocates a non-overlapping subnet from the available pool and creates an AllocationOnlyVmnetNetwork. However, if you require specific IP ranges for firewall rules or service discovery, you should explicitly define the subnet using the --subnet flag.
What is the difference between --internal and omitting the flag?
The --internal flag sets NetworkMode.hostOnly in the NetworkConfiguration, which disables NAT and prevents the containers from reaching external networks. Without this flag, the network operates in NAT mode, allowing containers to access the internet through the host while remaining isolated from other container networks.
Does the custom subnet configuration support IPv6?
Yes. Use the --subnet-v6 flag to specify an IPv6 prefix such as fd00:1234::/48. The validation logic in DefaultNetworkService checks IPv6 prefixes for collisions similarly to IPv4, though IPv6 allocation is not automatic—you must explicitly provide the CIDR if you require IPv6 addressing.
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 →