Skip to main content

Docker DNS

Docker's embedded DNS server (127.0.0.11) that runs inside every container on a user-defined network, resolving container names and network aliases to IP addresses without any manual configuration.

Docker DNS — How Containers Find Each Other by Name

What Is Docker DNS in Simple Terms?

When a container wants to reach another container, it needs to know its IP address. But container IPs change every time a container restarts. Docker's embedded DNS server solves this — it automatically assigns each container a DNS hostname matching its container name, and updates the DNS record every time the container restarts with a new IP.

Containers use Docker DNS automatically on user-defined networks. On the default bridge network, there is no DNS — containers are on their own.

sequenceDiagram participant API as api container participant DNS as Docker DNS 127.0.0.11 participant DB as postgres container API->>DNS: resolve postgres DNS-->>API: 172.18.0.3 Note over DB: postgres restarts, gets new IP API->>DNS: resolve postgres DNS-->>API: 172.18.0.4 (updated automatically)

How Docker DNS Works

Bash
# Create user-defined network
docker network create payment-network
# Run containers on it
docker run -d --name api --network payment-network node:20-alpine sleep 3600
docker run -d --name db --network payment-network postgres:15 \
-e POSTGRES_PASSWORD=secret
# Check DNS config inside the container
docker exec api cat /etc/resolv.conf
# nameserver 127.0.0.11 <- Docker's embedded DNS
# options ndots:0
# Resolve db by name
docker exec api nslookup db
# Server: 127.0.0.11
# Name: db
# Address: 172.18.0.3
# Restart db — it gets a new IP
docker restart db
docker exec api nslookup db
# Name: db
# Address: 172.18.0.4 <- updated automatically

DNS in Docker Compose

YAML
version: "3.8"
services:
payment-api:
environment:
DB_HOST: postgres # service name = DNS hostname
REDIS_HOST: redis # works automatically in Compose
postgres:
image: postgres:15
redis:
image: redis:7-alpine
# Compose auto-creates a user-defined network
# All services resolve each other by service name

Network Aliases

Bash
# Give a container additional DNS names
docker run -d \
--name postgres-primary \
--network app-network \
--network-alias db \
--network-alias database \
postgres:15 -e POSTGRES_PASSWORD=secret
# Now reachable by three names:
# postgres-primary, db, database
docker exec api ping db # works
docker exec api ping database # works

Default Bridge Has No DNS

Bash
# Default bridge — no DNS
docker run -d --name web nginx
docker run -d --name api node:20-alpine sleep 3600
docker exec api nslookup web
# ping: bad address 'web' <- FAILS — no DNS on default bridge
# Fix: create user-defined network
docker network create app-network
docker network connect app-network web
docker network connect app-network api
docker exec api nslookup web # now works

Quick Reference & Troubleshooting Commands

Problem Cause Fix
nslookup fails inside container On default bridge network Create and use a user-defined network
Name resolves to stale IP Client cached old resolution Restart the calling container or lower TTL expectations
Two containers can't resolve each other On different networks docker network connect <network> <container>
Alias not resolving Alias set after container started Aliases apply at connect time; reconnect the container with --alias
Compose service name unresolvable Service on different Compose project network Ensure both services are in the same docker-compose.yml or share a network
Tip

Always create a user-defined bridge network for any multi-container application. The one-line command docker network create app-network takes seconds and immediately gives you DNS, better isolation, and stable container-name resolution.

Remember

The default bridge network has no DNS — containers can only find each other by IP address, which changes on every restart. User-defined bridge networks automatically provide DNS resolution by container name.

Common Mistake

Hardcoding container IP addresses in application configuration. Container IPs change on every restart. Always use container names (on user-defined networks) or service names (in Compose) — Docker DNS resolves them to the current IP automatically.

Security

Docker's embedded DNS server only resolves names within the same Docker network. Containers on separate networks cannot resolve each other's names even if they happen to know an IP — treat separate networks as a real isolation boundary, not just a naming convenience.

Frequently Asked Questions

Why can't containers resolve each other by name on the default bridge network?

Docker's embedded DNS server at 127.0.0.11 only activates automatic name resolution for containers on a user-defined network — the default `bridge` network Docker creates on install doesn't get this treatment for legacy compatibility reasons, and containers there can only reach each other by IP or via the deprecated `--link` flag. This is one of the main reasons Docker docs recommend always creating a custom network (or using Compose, which creates one automatically) rather than relying on the default bridge.

What's a common DNS-related mistake in multi-network container setups?

Assuming a container can resolve another container by name across two different Docker networks it isn't attached to — the embedded DNS server only resolves names within the same network, so a container needs to be explicitly connected to every network whose members it needs to reach by name. Also, container name resolution changes on restart if you don't use a fixed network alias, since the embedded DNS keys off the container's current name and network membership, not a stable identifier.