How to Configure Host DNS for Containers on macOS Using the Container Tool

On macOS, you configure host DNS for containers by either passing --dns flags to individual containers or creating a persistent resolver domain via container system dns create and the [dns] section in ~/.config/container/config.toml.

The apple/container repository provides a native macOS container runtime that integrates with the host’s DNS resolution system. Unlike Linux, macOS requires specific resolver configuration to allow host-to-container and container-to-host name resolution, which this tool handles through system-level DNS entries and per-container runtime settings.

Per-Container DNS Configuration

Individual containers can override default DNS behavior using runtime flags. The CLI parses these flags in Sources/Services/ContainerAPIService/Client/Flags.swift and stores them in a ContainerConfiguration.DNSConfiguration object defined in Sources/ContainerResource/Container/ContainerConfiguration.swift.

When launching a container, the runtime applies these settings as shown in Sources/Services/RuntimeLinux/Server/RuntimeService.swift.

Available flags include:

  • --dns <ip> – Specify nameserver IP addresses
  • --dns-domain <domain> – Set the DNS domain
  • --dns-option <opt> – Pass resolver options
  • --dns-search <domain> – Configure search domains

Configure a container with custom nameservers:

container run --dns 8.8.8.8 --dns 1.1.1.1 \
    --dns-search example.com \
    alpine:latest

The container will query 8.8.8.8 and 1.1.1.1 for resolution and append example.com to bare hostnames.

System-Level Host DNS Configuration

For persistent DNS configuration that affects how the macOS host resolves container names, the tool supports two methods: configuration file entries and command-line domain creation.

Configuring via config.toml

The top-level configuration file at ~/.config/container/config.toml decodes into ContainerSystemConfig (see Sources/ContainerPersistence/ContainerSystemConfig.swift). The dns property uses the DNSConfig struct:

final public class DNSConfig: Codable, Sendable {
    public let domain: String?
    public init(domain: String? = nil) { self.domain = domain }
}

Add a default domain to all containers by editing ~/.config/container/config.toml:

[dns]
domain = "test"

With this setting, my-web-server becomes reachable as my-web-server.test from the host, and container ls displays the full hostname.

Creating a Host-Side DNS Domain

The container system dns create command generates a macOS resolver file under /etc/resolver/<domain>. This requires sudo privileges and registers the domain with the macOS DNS cache.

Create a domain for container-to-host communication:

sudo container system dns create host.container.internal \
    --localhost 203.0.113.113

This configuration writes /etc/resolver/host.container.internal and enables containers to resolve http://host.container.internal:8000 to reach a service running on the host.

Container-to-Host DNS Resolution

When the --localhost <ipv4> flag is supplied to container system dns create, the specified IPv4 address becomes the A record for the domain. This mechanism, documented in docs/how-to.md, bridges the container network to the host.

The DNSConfig struct in ContainerSystemConfig.swift stores the domain configuration, while the runtime ensures consistent application across container launches.

Verifying DNS Configuration

Verify that macOS recognizes the resolver entry:

scutil --dns | grep host.container.internal

Expected output:


nameserver[0] : 203.0.113.113

List all configured DNS domains:

container system dns list

This displays all domains created via container system dns create, along with their associated localhost addresses.

Summary

  • Per-container DNS is configured via --dns, --dns-search, and related flags parsed in Flags.swift and applied through RuntimeService.swift.
  • System-level DNS is controlled through the [dns] section in ~/.config/container/config.toml, decoded by ContainerSystemConfig.swift.
  • Host resolver integration requires sudo container system dns create, which writes to /etc/resolver/ and registers the domain with macOS.
  • Container-to-host bridging uses the --localhost flag to create A records pointing to host services.
  • Verification uses standard macOS tools like scutil --dns and container system dns list.

Frequently Asked Questions

How do I make a container reach a service running on my Mac host?

Use sudo container system dns create <domain> --localhost <host-ip> to create a DNS entry that resolves to your host's IP address within the container network. As documented in docs/how-to.md, this writes a resolver file to /etc/resolver/ and allows containers to connect to host services using the configured domain.

Where does the Container tool store its DNS configuration?

The tool stores system-level DNS configuration in ~/.config/container/config.toml, which decodes into the ContainerSystemConfig struct in Sources/ContainerPersistence/ContainerSystemConfig.swift. Runtime per-container DNS settings are stored in ContainerConfiguration.DNSConfiguration within each container's runtime configuration.

Can I use custom DNS servers for specific containers without affecting the system?

Yes. Pass --dns <ip> flags to container run or container create. These flags are parsed in Sources/Services/ContainerAPIService/Client/Flags.swift and stored in the container-specific DNSConfiguration object without modifying system-wide DNS settings.

Why does container system dns create require sudo privileges?

The command requires sudo because it writes resolver files to /etc/resolver/, which is a protected system directory on macOS. This integration allows the macOS native resolver to forward queries for the specified domain to the container's virtual network.

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 →