How to Configure DNS Resolution for Containers with Custom Domains
The Apple Container toolchain enables custom domain resolution through an embedded DNS server that creates macOS resolver files in /etc/resolver and appends configured domains to container hostnames.
The apple/container repository provides a container runtime with built-in DNS resolution capabilities. By leveraging the DNSConfig struct defined in ContainerSystemConfig.swift, you can configure DNS resolution for containers with custom domains that resolve to container IP addresses from the host system.
Understanding the DNS Architecture
The DNS configuration resides in the top-level ContainerSystemConfig struct located in Sources/ContainerPersistence/ContainerSystemConfig.swift. This struct contains a dns property that instantiates DNSConfig, which stores the optional custom domain for container hostname resolution.
final public class DNSConfig: Codable, Sendable {
public let domain: String? // ← the custom domain, if any
…
}
When the runtime loads configuration from config.toml or CLI flags, it uses the domain value to perform two critical operations: creating a macOS resolver file under /etc/resolver that forwards queries to the embedded DNS service listening on 127.0.0.1, and appending the domain suffix to container hostnames (e.g., transforming my-web-server into my-web-server.test).
Setting Up the macOS Resolver File
Before containers can resolve custom domains, you must create a resolver file that tells macOS to forward DNS queries for your specific domain to the container's embedded DNS server.
Create the resolver file using privileged commands:
sudo mkdir -p /etc/resolver
echo "nameserver 127.0.0.1" | sudo tee /etc/resolver/test
This configuration directs all queries for the .test domain to the embedded DNS service running on localhost. The file path /etc/resolver/test corresponds to the domain name you intend to use.
Configuration Methods
You can specify the custom DNS domain using either CLI flags or the configuration file. Both methods interact with the DNSConfig struct's domain property.
Using the Command Line Interface
The runtime exposes specific flags for DNS configuration as documented in docs/command-reference.md:
--dns <ip>: Sets the DNS nameserver IP address (defaults to127.0.0.1)--dns-domain <domain>: Defines the custom domain appended to container hostnames--dns-search <domain>: Adds a search suffix for the host's resolver
Launch a container with a custom domain:
container run --dns-domain test --name my-service my-image
Using the Configuration File
For persistent configuration, add a [dns] section to your config.toml file as documented in docs/container-system-config.md:
[dns]
domain = "test"
When specified in config.toml, all containers launched by the runtime automatically receive the configured domain suffix without requiring CLI flags.
Practical Implementation Workflow
Follow this complete workflow to enable and verify custom domain resolution:
-
Create the resolver file (requires
sudo):sudo mkdir -p /etc/resolver echo "nameserver 127.0.0.1" | sudo tee /etc/resolver/dev -
Launch the container with the custom domain:
container run --dns-domain dev --name my-web-server my-image -
Verify DNS resolution from the host:
ping my-web-server.devThe ping should resolve to the container's IP address, confirming that the host resolver forwards queries to the embedded DNS.
-
Clean up when finished:
sudo rm /etc/resolver/devRemove the resolver file to disable DNS resolution for that domain.
Summary
- The
DNSConfigstruct inContainerSystemConfig.swiftstores the optional custom domain for container DNS resolution. - The runtime creates macOS resolver files under
/etc/resolverto forward domain queries to the embedded DNS server at127.0.0.1. - Use
--dns-domainflag for ad-hoc configuration or the[dns]section inconfig.tomlfor persistent settings. - Container hostnames automatically append the custom domain suffix (e.g.,
container-name.custom-domain).
Frequently Asked Questions
Where does the container runtime store DNS configuration?
The DNS configuration is stored in the DNSConfig class within Sources/ContainerPersistence/ContainerSystemConfig.swift. This class contains a single optional domain property that specifies the default DNS domain appended to container hostnames. The runtime populates this property from either config.toml or CLI flags when the container system initializes.
What is the default address for the embedded DNS server?
According to the command reference in docs/command-reference.md, the embedded DNS server listens on 127.0.0.1 by default. You can override this using the --dns flag when launching containers, though the resolver file in /etc/resolver must point to the same address for host-side resolution to function.
How do I remove a custom DNS domain configuration?
To remove a custom domain, delete the corresponding resolver file from /etc/resolver/ using sudo privileges. For example, sudo rm /etc/resolver/test removes the .test domain configuration. As documented in examples/container-machine-vscode/README.md, this cleanup step prevents the host from attempting to resolve stale domain names after you stop using the container runtime.
Can I configure multiple custom DNS domains simultaneously?
The DNSConfig struct currently supports a single optional domain field. However, you can manually create multiple resolver files in /etc/resolver/ for different domains (e.g., /etc/resolver/dev and /etc/resolver/staging), each pointing to 127.0.0.1. You would then launch containers with the appropriate --dns-domain flag for each specific domain you want to use.
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 →