How to Configure Network Subnets and MAC Addresses for Containers in apple/container

Use the --subnet and --subnet-v6 flags when creating a network to define IPv4/IPv6 CIDR ranges, and specify a custom MAC address with the --mac-address flag when running or creating a container.

The apple/container runtime provides precise control over container networking through CLI flags that map directly to underlying Swift structs. Whether you need to isolate workloads with custom IP ranges or enforce deterministic MAC addresses for DHCP reservations, you can configure network subnets and MAC addresses for containers using straightforward command options that populate NetworkConfiguration and AttachmentOptions types.

Defining Network Subnets with network create

When you create a network, the CLI accepts optional flags to specify the IP address space. These values are transformed into CIDRv4 and CIDRv6 types and stored in the NetworkConfiguration struct defined in Sources/ContainerResource/Network/NetworkConfiguration.swift.

IPv4 Subnet Configuration (--subnet)

The --subnet flag accepts an IPv4 CIDR notation (e.g., 10.0.0.0/24). According to the source code in Sources/ContainerCommands/Network/NetworkCreate.swift, this flag maps to the ipv4Subnet property of NetworkConfiguration.

The flag is defined as an @Option with a custom transform that validates the input:

@Option(
    name: .customLong("subnet"),
    help: "Set subnet for a network",
    transform: { try CIDRv4($0) })
var ipv4Subnet: CIDRv4? = nil

When the command executes (lines 69–76 of NetworkCreate.swift), it instantiates a NetworkConfiguration with the parsed value and passes it to the NetworkClient, which forwards the configuration to the network plugin.

IPv6 Subnet Configuration (--subnet-v6)

Similarly, the --subnet-v6 flag accepts an IPv6 prefix (e.g., fd01::/48). This maps to NetworkConfiguration.ipv6Subnet in the same source files. The CLI validates the input using the CIDRv6 type before storing it in the configuration model.

Assigning MAC Addresses to Container Attachments

You can assign a specific MAC address to a container's network interface during container creation. The runtime stores this value in an AttachmentOptions struct and transmits it via XPC to the network service.

Using the --mac-address Flag

When running container run or container create, include the --mac-address option followed by a valid MAC address (e.g., 02:42:ac:11:00:02). The CLI parses this string into a MACAddress value and stores it in the AttachmentOptions struct defined in Sources/ContainerResource/Network/Attachment.swift.

Internal Flow to the Network Service

The NetworkClient.createAttachment method (in Sources/Services/Network/Client/NetworkClient.swift) adds the MAC address to the XPC request using the NetworkKeys.macAddress key defined in Sources/Services/Network/Client/NetworkKeys.swift.

On the runtime side, DefaultNetworkService (in Sources/Services/Network/Server/DefaultNetworkService.swift) receives the request. If you provide a MAC address, the service uses that value; if omitted, it generates a deterministic MAC address automatically.

Complete Configuration Examples

The following examples demonstrate how to configure network subnets and MAC addresses for containers using the apple/container CLI.

Create a network with custom IPv4 and IPv6 subnets:

container network create mynet \
    --subnet 10.0.0.0/24 \
    --subnet-v6 fd01::/48

Run a container on that network with a specific MAC address:

container run -d \
    --name myapp \
    --network mynet \
    --mac-address 02:42:ac:11:00:02 \
    docker.io/library/nginx:latest

Under the hood, the CLI constructs these Swift types:

let config = try NetworkConfiguration(
    name: "mynet",
    mode: .nat,
    ipv4Subnet: try CIDRv4("10.0.0.0/24"),
    ipv6Subnet: try CIDRv6("fd01::/48"),
    labels: .init(),
    plugin: "container-network-vmnet",
    options: [:]
)

let attachment = AttachmentOptions(
    hostname: "myapp",
    macAddress: try MACAddress("02:42:ac:11:00:02"),
    mtu: nil
)

Summary

  • Use --subnet with network create to define IPv4 CIDR ranges that map to NetworkConfiguration.ipv4Subnet in Sources/ContainerResource/Network/NetworkConfiguration.swift.
  • Use --subnet-v6 to specify IPv6 prefixes stored in NetworkConfiguration.ipv6Subnet.
  • Use --mac-address with container run or create to set a deterministic MAC address, parsed into AttachmentOptions and sent via NetworkClient using the NetworkKeys.macAddress key.
  • The runtime validates CIDR formats during parsing via CIDRv4 and CIDRv6 transforms, and handles MAC address assignment in DefaultNetworkService, generating one automatically if not provided.

Frequently Asked Questions

What CIDR formats does apple/container support for subnet configuration?

The runtime accepts standard IPv4 CIDR notation (e.g., 192.168.1.0/24) for the --subnet flag and IPv6 prefix notation (e.g., fd00::/64) for the --subnet-v6 flag. The CLI transforms these strings into strong types CIDRv4 and CIDRv6 during the parsing phase in NetworkCreate.swift.

Can I change a container's MAC address after it is running?

No, the MAC address is configured during the attachment creation phase. The NetworkClient.createAttachment method transmits the MAC address via XPC when the container starts, and DefaultNetworkService binds it to the interface at that time. To change the MAC address, you must recreate the container with the --mac-address flag.

How does the runtime handle MAC address collisions?

According to the implementation in Sources/Services/Network/Server/DefaultNetworkService.swift, if you do not specify a MAC address, the runtime generates a deterministic address based on the container configuration. If you provide a custom MAC address, the runtime uses that exact value. You should ensure uniqueness manually when assigning specific addresses, as the runtime does not perform collision detection against other manually assigned addresses.

Where is the network subnet configuration stored?

The subnet definitions reside in the NetworkConfiguration struct (defined in Sources/ContainerResource/Network/NetworkConfiguration.swift). When you create a network, the CLI builds this struct and passes it to the NetworkClient, which persists the configuration through the network plugin specified in the plugin property (typically container-network-vmnet).

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →