Resolving DNS failures in Compose networks
The most common Compose-in-DevContainer failure is an app that can’t resolve db or redis by name, even though both containers are running. The cause is almost always that the services aren’t sharing a user-defined network, so Docker’s embedded DNS resolver never gets involved. This page diagnoses and fixes service-name resolution in a Compose stack. It extends the Debugging Network & DNS Issues in Containers cluster.
Prerequisites
- A Compose-backed DevContainer (
dockerComposeFile+service) dnsutils/iproute2available in the app container for diagnosis- Docker Engine 24+ with Compose v2
How-To Steps
-
Reproduce the failure precisely — resolution, not just connectivity:
devcontainer exec --workspace-folder . getent hosts db || echo "name does not resolve" -
Confirm the embedded resolver is present. On a user-defined network,
/etc/resolv.confpoints at127.0.0.11:devcontainer exec --workspace-folder . cat /etc/resolv.conf | grep 127.0.0.11 \ || echo "not on a user-defined network" -
Put every service on one explicit network so names resolve:
services: app: build: . command: sleep infinity networks: [devnet] db: image: postgres:16-alpine@sha256:1f3d... networks: [devnet] redis: image: redis:7-alpine networks: [devnet] networks: devnet: driver: bridge -
Recreate the stack so the network change takes effect, then verify resolution:
devcontainer up --workspace-folder . --remove-existing-container devcontainer exec --workspace-folder . getent hosts db redis # both resolve to container IPs -
Add a host alias only if a service must be reachable under a second name:
services: db: networks: devnet: aliases: [database, primary-db]
Common Pitfalls
| Symptom | Root Cause | Remediation |
|---|---|---|
db does not resolve | Services on the default bridge | Attach all services to one user-defined network |
| Resolves after manual restart only | Network change not applied | Recreate the stack with --remove-existing-container |
| Resolves to wrong container | Duplicate service alias across networks | Keep one alias per name on the shared network |
| Public DNS works, service names don’t | Embedded resolver bypassed | Confirm 127.0.0.11 is in resolv.conf |
Conclusion
The essential invariant: Docker only resolves service names for containers on the same user-defined network. Declare one network, attach every service to it, and recreate the stack — service-name DNS then works deterministically, with no hardcoded IPs.
FAQ
Why does it work without a network block in a standalone docker compose up?
Compose creates a default project network automatically there. In a DevContainer the wiring can differ, so declaring an explicit network removes the ambiguity.
Can I just use container IPs instead? No — container IPs change on every recreate. Service-name resolution on a shared network is the only stable approach.
Related
- Debugging Network & DNS Issues in Containers — the parent cluster.
- Configuring a Postgres service in a DevContainer Compose stack — a stack that depends on this resolution.
- Docker Compose Integration for Multi-Service Apps — the broader orchestration cluster.