Every container has its own network namespace: its own interfaces, IPs, routing table and loopback interface. localhost (127.0.0.1) inside a container is that container's loopback, not the host's and not another container's.
┌─ host ──────────────────────────────────────────────┐
│ localhost:8080 ──► published port of counter │
│ │
│ ┌─ counter ──────────┐ ┌─ redis ──────────┐ │
│ │ lo 127.0.0.1 │ │ lo 127.0.0.1 │ │
│ │ eth0 172.18.0.3 │ │ eth0 172.18.0.2 │ │
│ │ listens :8080 │ │ listens :6379 │ │
│ └────────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────┘
inside counter: localhost:6379 → counter itself → refused
redis:6379 → 172.18.0.2 → workslocalhost used in | Refers to |
|---|---|
| A shell on the host | The host |
| A container | That same container |
A published port (-p 8080:8080) | Applies to the host's interfaces only |
Symptom 1: the app cannot reach its database
The visit counter reads its Redis host from REDIS_HOST. Set to localhost, it exits at startup:
docker logs counterError: connect ECONNREFUSED 127.0.0.1:6379
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1607:16) {
code: 'ECONNREFUSED'
}ECONNREFUSED 127.0.0.1 means: the name resolved to the loopback, and nothing listens there. Environment variables are fixed when a container is created, so recreate it with the Redis container's name:
docker rm counter
docker run -d --name counter --network stats -p 8080:8080 -e REDIS_HOST=redis stackmonsters/visit-counter:1.0
docker logs countervisit-counter listening on :8080 (redis at redis:6379)Symptom 2: a reverse proxy returns 502
An nginx config that forwards to localhost:
server {
listen 80;
location / {
proxy_pass http://localhost:8080;
}
}Every request returns 502 Bad Gateway, and the nginx log shows the reason:
[error] 29#29: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "http://localhost:8080/", host: "localhost"Replace localhost with the container name (proxy_pass http://counter:8080;) and run docker restart proxy. nginx reads its config at startup.
Error messages and what they mean
| Error | Cause |
|---|---|
ECONNREFUSED 127.0.0.1:PORT | The app used localhost; nothing listens on that port in its own container |
getaddrinfo ENOTFOUND NAME | The name does not resolve: wrong name, or the containers share no user-defined network |
nginx 502 + connect() failed (111) | The upstream address answered with a refusal |
nginx exits: host not found in upstream | The upstream name does not resolve when nginx starts |