Hardcoding IP addresses in your containers? Docker Compose provides automatic DNS-based service discovery. Each service can reach another using just the service name.
How it works
Docker Compose creates a default network and registers each container with an internal DNS server. The DNS name matches the service name in your compose.yml.
services:
web:
image: nginx
environment:
# Just use the service name!
API_URL: http://api:3000
DB_HOST: postgres
api:
image: myapi
environment:
DATABASE_URL: postgres://user:pass@postgres:5432/mydb
postgres:
image: postgres:15
No configuration needed. The web service connects to api using http://api:3000, and api connects to postgres using the hostname postgres.
Verify DNS resolution
Check what’s actually happening:
# See what IP 'postgres' resolves to
docker compose exec web nslookup postgres
Output:
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: postgres
Address: 172.18.0.3
Test connectivity:
docker compose exec web ping -c 2 api
Multiple instances
When scaling, DNS returns all container IPs:
services:
worker:
image: myworker
deploy:
replicas: 3
docker compose up -d --scale worker=3
docker compose exec web nslookup worker
# Returns 3 IP addresses for round-robin
Common gotchas
Using container names instead of service names:
services:
web:
container_name: my-web-container # Don't use this name for connections!
# ...
Always use the service name (web), not the container name.
Services on different networks: Services must be on the same network to resolve each other. By default, Compose creates one network for all services.
Real production example
Here’s how we use this at Docker:
services:
api:
image: docker/api:latest
environment:
# Service names for all connections
CACHE_URL: redis://cache:6379
SEARCH_URL: http://search:9200
METRICS_URL: http://metrics:9090
cache:
image: redis:7-alpine
search:
image: elasticsearch:8.11
metrics:
image: prom/prometheus
Each service finds the others by name. When containers restart and get new IPs, the DNS automatically updates.
Pro tip
For debugging network issues between services:
# Run a debug container on the same network
docker compose run --rm alpine sh
# Inside the container:
apk add curl bind-tools
nslookup api
curl http://api:3000/health
Service discovery through DNS eliminates configuration complexity. No more managing IP addresses or host files - Compose handles it all automatically.