Docker DNS Resolution Not Working: Fixes
The Problem
Containers can’t resolve domain names. You see errors like:
Could not resolve host: github.com
dial tcp: lookup registry-1.docker.io: no such host
getaddrinfo ENOTFOUND api.example.com
Name or service not known
Temporary failure in name resolution
This happens during docker build (can’t pull packages), at container startup (can’t reach databases by hostname), or at runtime (API calls fail).
The Cause
Docker containers use a built-in DNS server at 127.0.0.11 for resolving container names on custom networks. For external domains (anything not a container name), Docker falls back to the DNS servers configured on the host — typically from /etc/resolv.conf. The most common failures:
| Cause | Symptom | Frequency |
|---|---|---|
systemd-resolved conflict | Host /etc/resolv.conf points to 127.0.0.53 — unreachable from containers | Very common (Ubuntu/Debian default) |
| Docker daemon DNS misconfigured | No valid DNS in Docker config | Common |
Container on default bridge network | No Docker DNS, relies only on host DNS | Common |
| Firewall blocking outbound DNS | DNS packets dropped by UFW/iptables | Occasional |
| Alpine musl resolver limitations | IPv6 AAAA lookups fail or timeout | Occasional |
The Fix
Method 1: Fix systemd-resolved Conflict (Most Common)
On Ubuntu 22.04+, /etc/resolv.conf is a symlink to ../run/systemd/resolve/stub-resolv.conf, which points DNS at 127.0.0.53. This works for the host but not for Docker containers (they can’t reach 127.0.0.53 on the host’s loopback).
Option A: Point Docker at real DNS servers
Create or edit /etc/docker/daemon.json:
{
"dns": ["1.1.1.1", "9.9.9.9"]
}
Restart Docker:
sudo systemctl restart docker
This tells all containers to use Cloudflare and Quad9 instead of the host’s resolv.conf.
Option B: Fix resolv.conf to use the real resolver
sudo rm /etc/resolv.conf
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
This symlinks to systemd-resolved’s upstream resolvers (the real DNS servers), not the stub listener. Containers inherit these.
Option C: Replace resolv.conf entirely
sudo rm /etc/resolv.conf
echo -e "nameserver 1.1.1.1\nnameserver 9.9.9.9" | sudo tee /etc/resolv.conf
sudo chattr +i /etc/resolv.conf # Prevent systemd from overwriting
Method 2: Per-Container DNS Configuration
Override DNS for a specific container in docker-compose.yml:
services:
myapp:
image: myapp:latest
dns:
- 1.1.1.1
- 9.9.9.9
Or for a local DNS server (like Pi-hole):
services:
myapp:
image: myapp:latest
dns:
- 192.168.1.10
Method 3: Fix Docker Network DNS
Containers on Docker’s default bridge network don’t get Docker’s built-in DNS (127.0.0.11). Only containers on custom/user-defined networks get Docker DNS for container name resolution.
If containers can’t resolve each other by name:
services:
app:
networks:
- mynet
db:
networks:
- mynet
networks:
mynet:
driver: bridge
Now app can reach db by hostname.
Method 4: Fix Firewall Rules
If UFW or iptables blocks outbound DNS:
# Allow outbound DNS
sudo ufw allow out 53/tcp
sudo ufw allow out 53/udp
# Allow Docker bridge traffic
sudo ufw allow in on docker0
Check if DNS packets are reaching the internet:
docker run --rm alpine nslookup google.com 1.1.1.1
If this works but normal resolution doesn’t, the issue is in Docker’s DNS configuration, not the firewall.
Method 5: Fix Alpine DNS Issues
Alpine Linux uses musl libc, which handles DNS differently from glibc. Common issue: IPv6 AAAA lookups timeout before falling back to IPv4 A lookups, causing 5-second delays.
Add to your Dockerfile or container:
RUN echo "options single-request-reopen" >> /etc/resolv.conf
Or in Docker Compose:
services:
myapp:
dns_opt:
- single-request-reopen
Prevention
1. Always Use Custom Networks
Define networks in your Docker Compose files. Never rely on the default bridge for DNS resolution between containers.
2. Set DNS in daemon.json
Configure Docker-wide DNS once:
{
"dns": ["1.1.1.1", "9.9.9.9"]
}
3. Test DNS Early
Add a DNS test to your container startup or health check:
healthcheck:
test: ["CMD-SHELL", "nslookup example.com || exit 1"]
interval: 30s
timeout: 5s
4. Use IP Addresses for Critical Dependencies
For database connections in the same Compose stack, use the Docker service name (which resolves via Docker DNS). For external services, consider using IPs if DNS instability is a concern.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments