Q: How does Container DNS and Service Discovery work in Docker?

Answer:

Docker has a built-in DNS server that enables containers to discover and communicate with each other by name instead of IP address.

How It Works

When you create a custom bridge network, Docker runs an embedded DNS server at 127.0.0.11. Every container on that network automatically registers its container name as a DNS hostname.

docker network create backend
docker run -d --name api --network backend myapi
docker run -d --name db --network backend postgres

# Inside the "api" container:
ping db           # Resolves to the postgres container's IP ✅
curl http://db:5432  # Works by name ✅

Default Bridge vs Custom Bridge

FeatureDefault BridgeCustom Bridge
DNS resolution by name❌ No✅ Yes
Container isolationShared with all default containersIsolated per network
Legacy --link needed?Yes (deprecated)No

[!WARNING] The --link flag is deprecated. Always use custom bridge networks for container-to-container communication.

Network Aliases

You can give a container multiple DNS names using --network-alias:

docker run -d --name postgres-primary \
    --network backend \
    --network-alias db \
    --network-alias database \
    postgres

# Other containers can reach it via "postgres-primary", "db", OR "database"

Docker Compose — Automatic Service Discovery

In Docker Compose, each service name automatically becomes a DNS hostname on the shared network.

services:
  api:
    build: ./api
    depends_on:
      - db
  db:
    image: postgres:16

Inside the api container, db resolves to the Postgres container. No manual network configuration needed.

Round-Robin DNS (Load Balancing)

If multiple containers share the same network alias, Docker's DNS returns all their IPs in a round-robin fashion:

docker run -d --network backend --network-alias worker myworker
docker run -d --network backend --network-alias worker myworker
docker run -d --network backend --network-alias worker myworker

# Resolving "worker" returns all 3 IPs, rotating order each time