# How to Configure a Local DNS Domain for Containers to Access Host Services

> Map a custom hostname to an IP address to let containers resolve and connect to host services. Use sudo container system dns create for seamless access.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-07-05

---

**Use `sudo container system dns create <domain> --localhost <ip>` to map a custom hostname to a specific IPv4 address, enabling containers to resolve and connect to host-bound services via the embedded DNS server.**

The `apple/container` project ships with an embedded DNS server that bridges networking between containers and the host system. Configuring a local DNS domain allows you to expose host services to containers using human-readable hostnames rather than hardcoded IP addresses, with automatic resolution handled by the `LocalhostDNSHandler` component.

## Select a Safe IP Address Range

Before creating a DNS entry, choose an IPv4 address that will not conflict with actual network infrastructure. The source code recommends using documentation blocks or private ranges that are guaranteed not to route to real hosts:

- **Documentation ranges**: `203.0.113.0/24` (TEST-NET-3) or `198.51.100.0/24` (TEST-NET-2)
- **Private ranges**: `172.16.0.0/12` or specific unused addresses within your local network

This prevents accidental traffic leakage while ensuring the host can bind services to the chosen address.

## Register the Local DNS Domain

Create the DNS mapping using the container CLI. This command writes a resolver file to `/etc/resolver/` (on macOS) and registers the mapping with the container's internal DNS server:

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

```

For example, to map `host.container.internal` to `203.0.113.113`:

```bash
sudo container system dns create host.container.internal --localhost 203.0.113.113

```

The system validates the input and immediately makes the domain resolvable for all containers using the container runtime.

## How the DNS Resolution Works

### LocalhostDNSHandler Implementation

In [`Sources/APIServer/LocalhostDNSHandler.swift`](https://github.com/apple/container/blob/main/Sources/APIServer/LocalhostDNSHandler.swift), the DNS server implements `LocalhostDNSHandler` to manage dynamic hostname resolution. This component uses `DirectoryWatcher` to monitor the resolver directory for changes and maintains an in-memory lookup table of active domains.

When DNS queries arrive, the handler consults its internal `[DNSName: IPv4Address]` dictionary to answer requests for locally configured domains.

### Resolver File Parsing

The handler parses resolver files using the pattern defined in `HostDNSResolver.localhostOptionsRegex`. Each valid entry builds a mapping entry that associates the DNS name with the specified IPv4 address, enabling the server to return the correct A record when containers query for the custom domain.

### Automatic Search Domain Configuration

As defined in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift), the `DNSConfig.defaultDomain` property automatically populates the search list in container resolvers. This means containers can resolve the custom domain using unqualified hostnames (e.g., `host.container.internal` resolves correctly without suffixes).

## Complete End-to-End Example

The following workflow demonstrates running a Python HTTP server on the host and accessing it from a container using the custom DNS domain:

```bash

# 1. Choose a non-conflicting IP from the documentation range

IP=203.0.113.113
DOMAIN=host.container.internal

# 2. Register the domain with the container DNS service

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

# 3. Start a simple HTTP server on the host (binding to the chosen IP)

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

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

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

# Output: hello

```

The container sends the DNS query to the host's embedded DNS server, which returns `203.0.113.113`, allowing the curl request to reach the Python server.

## Removing the DNS Configuration

To clean up the DNS entry when it is no longer needed:

```bash
sudo container system dns delete <domain-name>

```

This removes the resolver file from `/etc/resolver/` and clears the entry from the `LocalhostDNSHandler` in-memory table, making the domain immediately unresolvable for new container lookups.

## Summary

- **Select a safe IP** from documentation (`203.0.113.0/24`) or private ranges (`172.16.0.0/12`) to avoid network conflicts
- **Use `container system dns create`** to register the domain and write resolver configuration to `/etc/resolver`
- **The `LocalhostDNSHandler`** watches resolver files and maintains a `[DNSName: IPv4Address]` dictionary for query responses
- **Containers automatically inherit** the `DNSConfig.defaultDomain` in their search list, enabling immediate resolution
- **Verify connectivity** by running services on the mapped IP and accessing them from containers using the custom hostname

## Frequently Asked Questions

### What IP address ranges are safe to use for local DNS domains?

Use addresses from **RFC 5737 documentation blocks** such as `203.0.113.0/24` or `198.51.100.0/24`, or private ranges like `172.16.0.0/12`. These addresses are guaranteed not to conflict with public internet routing according to the `apple/container` source recommendations.

### How do containers know to use the custom DNS domain?

The container runtime automatically appends the `DNSConfig.defaultDomain` (defined in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift)) to each container's DNS search list. This allows unqualified hostname resolution without manual `/etc/hosts` modifications inside containers.

### Where does the container DNS server store its configuration?

On macOS, the `container system dns create` command writes resolver files to `/etc/resolver/`. The `LocalhostDNSHandler` monitors this directory using `DirectoryWatcher` and updates its in-memory lookup table when files change, parsing entries that match `HostDNSResolver.localhostOptionsRegex`.

### Can I use multiple custom domains simultaneously?

Yes. Run `sudo container system dns create` multiple times with different domain names and IP addresses. The `LocalhostDNSHandler` maintains a dictionary mapping each unique DNS name to its corresponding IPv4 address, supporting parallel resolution for multiple host services.