docker-dns

A lightweight DNS server that resolves Docker container names to their IP addresses, enabling seamless networking between containers and the host.

Tests Release Go Report Card License Go Reference
$ docker run -d --name myapi nginx:alpine
$ dig myapi.docker +short
172.17.0.2
$ curl http://myapi.docker
<html>Welcome to nginx!</html>

Installation (Linux/Debian)

Important: Read the Systemd & DNS documentation for a deep overview on how systemd integrates with DNS resolution across distros.

Download and Install

Go to the Releases page, download the .deb for your version, and install:

wget https://github.com/MedUnes/docker-dns/releases/download/v1.0.4/docker-dns-1.0.4_amd64.deb
sudo dpkg -i docker-dns-1.0.4_amd64.deb

The installer automatically detects your DNS resolver and integrates accordingly:

SystemIntegration
Ubuntu (systemd-resolved)Drop-in config at /etc/systemd/resolved.conf.d/docker-dns.conf with routing domains (~docker)
Debian Desktop (NetworkManager)Dispatcher script at /etc/NetworkManager/dispatcher.d/docker-dns re-prepends nameserver after every NM event
Debian Server (plain resolv.conf)Prepends nameserver 127.0.0.153 to /etc/resolv.conf

If you use a custom resolver (dnsmasq, unbound, Pi-hole), see the Systemd & DNS documentation for manual integration examples.

Verify

systemctl status docker-dns

Uninstall

All integration changes are reversed automatically on removal:

sudo dpkg -r docker-dns

Features

  • Automatic DNS Resolution: resolve Docker container names with a custom TLD (default .docker) to their IP addresses. Supports multiple TLDs and containers on any Docker network.
  • Fallback DNS: forwards non-Docker queries in parallel to configurable upstream resolvers (default: 8.8.8.8, 1.1.1.1, 8.8.4.4), returning the first successful response.
  • Caching: TTL-based DNS cache with background eviction, size limits, and hit/miss telemetry.
  • Singleflight: concurrent cache misses for the same name are collapsed into a single Docker API call (thundering-herd protection).
  • Rate Limiting: per-IP token-bucket rate limiter with automatic idle cleanup.
  • Health & Metrics: HTTP server on :8080 exposes /health and /metrics (cache stats, query counts, error rates).
  • UDP + TCP: full DNS protocol support with EDNS0 handling and proper truncation.
  • Debian Package: .deb package with automatic systemd integration and clean uninstall.
  • Tested on 12 Configurations: full install -> resolve -> uninstall lifecycle CI on Ubuntu 20.04/22.04/24.04 and Debian 11/12/13, both server and desktop variants.
  • Lightweight: single Go binary, minimal resource footprint.

Architecture

The diagram below shows how a DNS query flows through the system, from the network listeners down to Docker or upstream resolvers.

docker-dns architecture

Queries for managed TLDs (like .docker or .local) are resolved by inspecting the matching Docker container. A singleflight gate prevents concurrent cache misses from hammering the Docker API. All other queries are forwarded in parallel to the configured upstream resolvers, returning the first successful response.

Configuration

The systemd service reads from /etc/docker-dns/docker-dns.conf (INI format). All settings are also available as CLI flags.

# /etc/docker-dns/docker-dns.conf
IP=127.0.0.153
TTL=300
TLD=docker,local
DEFAULT_RESOLVER=8.8.8.8,1.1.1.1,8.8.4.4

Full Reference

CLI FlagINI VariableDefaultDescription
--ipIP127.0.0.153IP address the DNS server listens on
--tldTLDdockerComma-separated managed TLDs for container resolution
--ttlTTL300TTL in seconds for cache entries and DNS responses
--resolversDEFAULT_RESOLVER8.8.8.8,1.1.1.1,8.8.4.4Comma-separated fallback DNS resolver IPs
--forward-timeoutX2sPer-resolver timeout for forwarded DNS queries
--rate-limitX100Max queries/sec per client IP (0 disables)
--rate-burstX50Burst allowance for rate limiting
--max-cache-sizeX10000Max DNS cache entries (0 = unlimited)
--http-addrX:8080Health/metrics HTTP server address (empty to disable)
--docker-timeoutX5sTimeout for Docker API calls
--docker-hostXautoDocker host override (defaults to DOCKER_HOST env / socket)
--log-levelXinfoLog level: debug, info, warn, error

After editing, restart the service:

sudo systemctl restart docker-dns

Configuration Notes

  • IP: typically in the loopback range (127.0.0.0/8), but can be any interface. Change if another service uses the default.
  • TTL: higher values improve performance for stable stacks; lower values give more real-time accuracy for dynamic containers.
  • TLD: supports multiple TLDs. With TLD=docker,local, both myapp.docker and myapp.local resolve to the container's IP.
  • Resolvers: specify multiple for redundancy. Can include your local DNS (Pi-hole, corporate resolver, etc.).

Usage

Resolve Containers by Name

dig mycontainer.docker @127.0.0.153 +short

Resolve External Domains

Non-Docker queries are forwarded to your fallback resolvers:

dig google.com @127.0.0.153 +short

Health Check

curl http://localhost:8080/health
# {"status":"ok"}

Metrics

curl http://localhost:8080/metrics
# {"queries_total":142,"cache_hits":98,"cache_misses":44,...}

CLI Help

sudo ./docker-dns -h
Usage of docker-dns:
  -ip string
      IP address the DNS server listens on (default "127.0.0.153")
  -tld string
      Comma-separated managed top-level domains for container resolution (default "docker")
  -ttl int
      TTL in seconds for cache entries and DNS responses (default 300)
  -resolvers string
      Comma-separated fallback DNS resolver IPs (default "8.8.8.8,1.1.1.1,8.8.4.4")
  -forward-timeout duration
      Per-resolver timeout for forwarded DNS queries (default 2s)
  -rate-limit float
      Max queries/sec per client IP; 0 disables rate limiting (default 100)
  -rate-burst int
      Burst allowance for per-IP rate limiting (default 50)
  -max-cache-size int
      Max DNS cache entries; 0 = unlimited (default 10000)
  -http-addr string
      Address for the health/metrics HTTP server; empty to disable (default ":8080")
  -docker-timeout duration
      Timeout for Docker API calls (default 5s)
  -docker-host string
      Docker host override (empty = use DOCKER_HOST env / socket default)
  -log-level string
      Log level: debug | info | warn | error (default "info")

Note: sudo (or root) is required because port 53 is a privileged port. The .deb package uses CAP_NET_BIND_SERVICE instead.

Systemd & DNS Integration

Docker's built-in DNS (127.0.0.11) only works container-to-container on user-defined networks. From the host, there's no way to resolve a container by name without manual intervention.

docker-dns solves this by running on the host and integrating with the system's DNS stack. Ubuntu and Debian handle DNS in fundamentally different ways, and the installer handles both automatically.

Full documentation covering systemd-resolved routing domains, plain resolv.conf, browser DNS-over-HTTPS caveats, and the tested configuration matrix is available in docs/Systemd.md.

Tested Configurations

OSVersionVariantDNS Method
NobleUbuntu 24.04Serversystemd-resolved + routing domain
NobleUbuntu 24.04Desktopsystemd-resolved + NM (dns=systemd-resolved)
JammyUbuntu 22.04Serversystemd-resolved + routing domain
JammyUbuntu 22.04Desktopsystemd-resolved + NM (dns=systemd-resolved)
FocalUbuntu 20.04Serversystemd-resolved + routing domain
FocalUbuntu 20.04Desktopsystemd-resolved + NM (dns=systemd-resolved)
TrixieDebian 13Serverplain resolv.conf
TrixieDebian 13DesktopNM dispatcher + resolv.conf
BookwormDebian 12Serverplain resolv.conf
BookwormDebian 12DesktopNM dispatcher + resolv.conf
BullseyeDebian 11Serverplain resolv.conf
BullseyeDebian 11DesktopNM dispatcher + resolv.conf

Build from Source

git clone https://github.com/medunes/docker-dns.git
cd docker-dns
make build

Run the binary:

sudo ./bin/docker-dns --ip=127.0.0.153 --tld=docker

Or download pre-built binaries from the Releases page.

Contributing

Contributions are welcome.

git checkout -b feature/YourFeature
git commit -am 'Add YourFeature'
git push origin feature/YourFeature

Then open a Pull Request on GitHub.

License

This project is licensed under the AGPL License: see the LICENSE file for details.