How to Configure DNS to Access Host Services from a Container

Apple Container provides an embedded DNS server that maps custom domain names to host IP addresses, allowing containers to resolve and connect to services running on the host via friendly DNS names.

The apple/container repository includes a built-in DNS resolution system that bridges the networking gap between macOS hosts and Linux containers. By configuring a custom DNS domain that points to a specific host IP address, you can access host-bound services from inside containers without hardcoding IP addresses or exposing ports externally.

How the DNS Resolution System Works

The container runtime runs an embedded DNS server that intercepts DNS queries from containers and resolves custom domains to host-local IP addresses. When you register a domain using the CLI, the system writes a resolver file to /etc/resolver on macOS and updates an in-memory lookup table.

According to the source code in Sources/APIServer/LocalhostDNSHandler.swift, the LocalhostDNSHandler class monitors the resolver directory using a DirectoryWatcher. When files change, it parses lines matching localhostOptionsRegex to build a [DNSName: IPv4Address] dictionary. This dictionary is used to answer DNS queries for custom domains, returning the mapped IP address to the requesting container.

The default domain suffix is controlled by DNSConfig.defaultDomain in Sources/ContainerPersistence/ContainerSystemConfig.swift, which automatically appends the local search domain to container resolver configurations.

Step-by-Step DNS Configuration

Select a Safe IPv4 Address Range

Choose an IP address that will not conflict with real networks. Apple recommends using documentation blocks such as 203.0.113.0/24 (TEST-NET-3) or private ranges like 172.16.0.0/12. Avoid using 127.0.0.1 directly, as this can cause routing issues within the container network namespace.

Register the DNS Domain

Use the container system dns create command to map your chosen IP to a hostname:

sudo container system dns create <domain-name> --localhost <ipv4-address>

This command creates a resolver file under /etc/resolver on macOS and registers the mapping with the container's DNS server. The LocalhostDNSHandler immediately updates its internal routing table to answer queries for the new domain.

Verify Container Resolution

Test the configuration by running a container that attempts to resolve the custom domain:

container run -it --rm alpine/curl curl http://<domain-name>:<port>

The container forwards DNS requests to the host's DNS server, which returns the configured IPv4 address. The request is then routed to the host service listening on that address.

Complete Working Example

The following example demonstrates mapping a custom domain to a documentation-range IP address and accessing a Python HTTP server from within a container:


# Choose a non-conflicting IP from the documentation range

IP=203.0.113.113
DOMAIN=host.container.internal

# Register the domain with the container DNS service

sudo container system dns create ${DOMAIN} --localhost ${IP}

# Start a simple HTTP server on the host (binding to localhost)

mkdir -p /tmp/test && cd /tmp/test && echo "hello" > index.html
python3 -m http.server 8000 --bind 127.0.0.1

# From a container, fetch the page using the DNS name

container run -it --rm alpine/curl curl http://${DOMAIN}:8000

# Output: hello

To remove the DNS mapping when finished:

sudo container system dns delete ${DOMAIN}

Key Implementation Files

The DNS functionality is implemented across several core components:

Summary

  • Apple Container uses an embedded DNS server (LocalhostDNSHandler) to resolve custom domains to host IP addresses.
  • Use safe IP ranges like 203.0.113.0/24 to avoid network conflicts when mapping host services.
  • Register domains with sudo container system dns create <domain> --localhost <ip> to write resolver files and update the DNS table.
  • Containers automatically inherit the local search domain from DNSConfig.defaultDomain, enabling immediate resolution without restarting the runtime.
  • Resolution is dynamic – the DirectoryWatcher detects changes to /etc/resolver files and updates the in-memory DNS table without requiring service restarts.

Frequently Asked Questions

What IP addresses are safe to use for host DNS mapping?

Use documentation-range addresses like 203.0.113.0/24 (TEST-NET-3) or private network ranges such as 172.16.0.0/12. These ranges are guaranteed not to conflict with public internet addresses and are specifically reserved for testing and documentation purposes.

How does the container DNS server know when I add a new domain?

The LocalhostDNSHandler in Sources/APIServer/LocalhostDNSHandler.swift uses a DirectoryWatcher to monitor /etc/resolver for changes. When you run container system dns create, the CLI writes a new resolver file, triggering the handler to parse the file and update its in-memory [DNSName: IPv4Address] dictionary used for query responses.

Where is the DNS configuration stored on macOS?

The container system dns create command writes resolver configuration files to /etc/resolver. macOS uses this directory to determine which DNS server should handle queries for specific domains. The container runtime reads these files to build its internal routing table.

Can I delete a DNS mapping after creating it?

Yes. Use sudo container system dns delete <domain-name> to remove the resolver file and unregister the mapping from the embedded DNS server. The DirectoryWatcher detects the file deletion and immediately removes the entry from the in-memory lookup table, preventing further resolution of that domain.

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 →