Problem Description
In a local AI training sandbox the microservices that compose the pipeline cannot locate the PostgreSQL instance. The typical error observed in the consuming service logs is:
2023-07-21T14:12:03.123Z microservice-a[12]: could not translate host name "postgres" to address: Name or service not known
Other variants that appear during the investigation include:
FATAL: could not connect to server: Connection refused (0x0000274D/10061)psql: error: could not connect to server: No such file or directoryERROR: could not resolve hostname "db" – DNS lookup failed inside container
The failure prevents the AI training pipeline from persisting model artifacts, loading configuration data, and generally halts the end‑to‑end workflow.
Root Cause Analysis
The core of the problem is a mismatch between the Docker Compose network topology and the DNS expectations of PostgreSQL client libraries. According to the PostgreSQL “Database Connection Settings” chapter, the client resolves the host parameter using the system resolver, which in a container is the Docker embedded DNS server. If the service name is not present in that DNS view, the resolver returns ENOTFOUND, leading to the “could not translate host name” error.
Evidence from the community shows two typical patterns that produce this state:
- A custom network is defined for GPU‑enabled containers, while the
postgresservice remains on the default network (GitHub issue 6715). - Explicit
network_mode: bridgeis set on the PostgreSQL service, which isolates it from the user‑defined overlay network used by the AI inference service (GitHub issue 8329).
In both cases the Docker embedded DNS does not publish the postgres name into the network namespace of the consuming containers, so DNS resolution fails before any authentication (as described in Chapter 33 “Client Authentication”).
Investigation and Debugging
The following step‑by‑step checks isolate the DNS mismatch:
- Inspect the Compose networks
docker-compose config | grep networks -A 5Expected output shows a single default network unless a custom one is declared.
- Verify which network each container is attached to
docker inspect -f '{{.Name}} {{range .NetworkSettings.Networks}}{{.NetworkID}} {{end}}' $(docker ps -q)Look for the
postgrescontainer ID and compare it with the IDs of the AI services. - Test DNS resolution from a consumer container
docker exec -it microservice-a sh -c 'getent hosts postgres || echo "lookup failed"'If the command prints “lookup failed”, the DNS entry is missing.
- Capture a packet trace (optional)
docker exec -it microservice-a tcpdump -i any -n udp port 53 -c 5The trace should show a DNS query to
127.0.0.11:53. A lack of response indicates the embedded DNS does not know the name. - Check PostgreSQL container logs for bind address
docker logs postgres | grep "listening on"The official image logs “listening on all IP addresses” by default; if it is bound only to
127.0.0.1, external containers cannot reach it.
Resolution
The fix consists of aligning all services on a single user‑defined network and removing any conflicting network_mode directives. Below is a before/after comparison of the docker-compose.yml file.
Before
version: "3.8"
services:
postgres:
image: postgres:15
environment:
POSTGRES_PASSWORD: secret
network_mode: bridge # <-- isolates container
microservice-a:
build: ./microservice-a
depends_on:
- postgres
# uses default network
inference:
build: ./inference
networks:
- gpu_net # custom network for GPU containers
networks:
gpu_net:
driver: bridge
After
version: "3.8"
services:
postgres:
image: postgres:15
environment:
POSTGRES_PASSWORD: secret
networks:
- app_net # <-- attach to shared network
microservice-a:
build: ./microservice-a
depends_on:
- postgres
networks:
- app_net
inference:
build: ./inference
networks:
- app_net
- gpu_net # keep GPU network if needed
networks:
app_net:
driver: bridge
gpu_net:
driver: bridge
Key changes:
- Removed
network_mode: bridgefrom the PostgreSQL service. - Created an explicit
app_netbridge network and attached every service that needs database access. - Preserved the
gpu_netfor GPU‑specific traffic while also joiningapp_netso DNS resolution works.
After applying the updated compose file, bring the stack down and up to ensure a clean network recreation:
docker-compose down -v
docker-compose up -d
Validation
Confirm that DNS resolution now succeeds and the database connection is established:
- From a consumer container:
docker exec -it microservice-a sh -c 'getent hosts postgres'Expected output:
172.20.0.2 postgres(IP will vary). - Attempt a direct psql connection:
docker exec -it microservice-a sh -c 'psql -h postgres -U postgres -c "SELECT 1;"'Expected output:
?column? ---------- 1 (1 row) - Check the PostgreSQL logs for successful authentication:
docker logs postgres | grep "authentication successful"A line similar to
2023-07-21 14:15:02.123 UTC [12] LOG: connection authorized: user=postgres database=postgresconfirms the handshake.
Prevention and Best Practices
- Define a single logical network for services that need to talk to each other. Use explicit network names instead of the default network to avoid accidental isolation.
- Avoid
network_mode: bridgeon individual services. This overrides Compose’s network handling and prevents DNS propagation. - Declare
depends_ononly for start‑order, not for network visibility. All services on the same network can resolve each other regardless of dependencies. - Enable healthchecks that verify DNS resolution. Example:
healthcheck: test: ["CMD", "pg_isready", "-h", "postgres"] interval: 10s timeout: 5s retries: 5 - Monitor Docker DNS errors. Alert on log patterns such as “could not translate host name” to catch mis‑configurations early.
Related Topic Hub: Data Infrastructure Troubleshooting Hub
FAQ
- Why does the error appear only after adding a GPU‑enabled external network?
Because the PostgreSQL container remained on the default network while the GPU containers were attached to a separate network. Docker DNS only resolves names within the same network scope, so the new containers could not seepostgres. - Can I keep
network_mode: bridgefor the PostgreSQL container?
No. Usingnetwork_mode: bridgecreates an independent Docker bridge that is not part of the Compose‑managed network, breaking DNS resolution for sibling services. - Is
depends_onsufficient to guarantee name resolution?
No.depends_ononly controls container start order. DNS visibility is governed solely by network membership. - What if I need the PostgreSQL container to be reachable from the host machine?
Expose the port on the shared network (e.g.,ports: ["5432:5432"]) or usedocker run -pon the host. The DNS name is still resolved only inside containers on the same network. - How can I debug DNS resolution without entering the container?
Usedocker network inspect <network_name>to view the list of containers and their assigned IPs. Verify that the service name appears underContainers→Nameentries.