Docker Compose — Service DNS Naming
One of Docker Compose’s most powerful features is automatic DNS. Every service name becomes a hostname that other services can use to connect. No IP addresses to manage, no manual network configuration.
How Service DNS Works
When Compose creates a network, it runs an embedded DNS server. Each service name becomes a DNS entry:
services:
api:
image: node:20
environment:
DB_HOST: db # ← Use service name as hostname
REDIS_HOST: cache # ← Use service name as hostname
db:
image: postgres:16
cache:
image: redis:7
┌────────────── Compose DNS ──────────────┐
│ │
│ Service Name → IP Address │
│ ───────────────────────── │
│ api → 172.18.0.2 │
│ db → 172.18.0.3 │
│ cache → 172.18.0.4 │
│ │
│ api container can: │
│ ping db → 172.18.0.3 │
│ ping cache → 172.18.0.4 │
│ │
│ db container can: │
│ ping api → 172.18.0.2 │
│ ping cache → 172.18.0.4 │
└──────────────────────────────────────────┘
Practical Example
A Node.js API connecting to PostgreSQL and Redis:
services:
api:
build: .
ports:
- "3000:3000"
environment:
# Use service names as hostnames
DATABASE_URL: postgres://admin:secret@db:5432/myapp
REDIS_URL: redis://cache:6379
depends_on:
- db
- cache
db:
image: postgres:16
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
cache:
image: redis:7-alpine
The api service connects to db:5432 and cache:6379 — using the service names as hostnames.
Testing DNS Resolution
You can verify DNS resolution inside a container:
# Shell into the api container
docker compose exec api sh
# Inside the container — ping other services
ping -c 1 db
# PING db (172.18.0.3): 56 data bytes
# 64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.098 ms
ping -c 1 cache
# PING cache (172.18.0.4): 56 data bytes
# 64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.085 ms
DNS Naming Rules
| Rule | Example |
|---|---|
| Service name = hostname | db service → hostname db |
| Case-sensitive | db ≠ DB |
| Only within same network | Services on different networks can’t resolve each other |
container_name doesn’t affect DNS |
DNS uses the service name, not the container name |
Common Connection Strings
| Database/Service | Connection String |
|---|---|
| PostgreSQL | postgres://user:pass@db:5432/dbname |
| MySQL | mysql://user:pass@db:3306/dbname |
| Redis | redis://cache:6379 |
| MongoDB | mongodb://user:pass@mongo:27017/dbname |
| Elasticsearch | http://elasticsearch:9200 |
| RabbitMQ | amqp://user:pass@rabbitmq:5672 |
Summary
| Concept | Detail |
|---|---|
| DNS resolution | Service name = hostname |
| No IP management | Compose handles it automatically |
| Scope | Within the same Compose network |
| Testing | docker compose exec <service> ping <other-service> |
Quick Reference
| Item | Detail |
|---|---|
| Service name = hostname | db service → hostname db |
| Connection string | postgres://user:pass@db:5432/mydb |
| Test DNS | docker compose exec api ping db |
| Scope | Same Compose network only |
| DNS server | Embedded in Docker network |
| Case sensitive | Service names are case-sensitive |