Networking: isolation, security and troubleshooting
When a connection fails, test the container and the path separately. Follow a ladder instead of guessing.
key idea / Docker itselfcontainer / good pathhost / watch outproblem / blockedneutral
The ladder
The most common trap
Where does it fail?
Isolation and security
Symptoms and commands
| Symptom | Likely cause | Check |
|---|---|---|
host curl: connection refused | no -p, or app on 127.0.0.1 | docker inspect Ports, listen address |
bad address 'api' | default bridge, or different network | docker network inspect |
| works by IP, fails by name | no DNS on the default bridge | use a user-defined network |
| published port exposed on the LAN | bound to 0.0.0.0 | bind to 127.0.0.1 |
| cross-host overlay silent | UDP 4789 blocked | firewall between swarm nodes |
| Command | Tells you |
|---|---|
docker inspect api --format '{{json .NetworkSettings.Ports}}' | what is published |
docker exec api ip addr / ip route | the stack the process really sees |
docker network inspect app | every container on that network |
tcpdump -i docker0 (on the host) | whether packets reach the bridge |
Try it yourself
Start from a container that is running and still refuses a connection. Each step answers one question.
-
Step 1 · The host curl fails
$ docker run -d --name api --rm nginx:1.27 $ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080 000 -
Step 2 · Is the container running?
$ docker ps --filter name=api CONTAINER ID IMAGE STATUS NAMES aa11bb22cc33 nginx:1.27 Up 4 seconds api -
Step 3 · Is a port published?
An empty mapping means the process can be healthy and the host still has no route to it.
$ docker inspect -f '{{json .NetworkSettings.Ports}}' api {"80/tcp":null} -
Step 4 · Does the process answer inside?
$ docker exec api wget -q -S -O /dev/null http://127.0.0.1:80 HTTP/1.1 200 OK -
Step 5 · Publish the port and curl again
$ docker stop api $ docker run -d --name api --rm -p 8080:80 nginx:1.27 $ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080 200 $ docker stop api
Recap
- Check the container, then the publish rule, then the process, then the network, then DNS, then packets.
- A process must listen on
0.0.0.0, not127.0.0.1, to be reachable through-p. - Test from inside, from a sibling container and from the host to find which layer fails.
- Use user-defined networks (and
--internal) as your isolation boundary.
Quick check
wget http://127.0.0.1:3000 works inside the container but the host curl is refused, and -p 8080:3000 is set. What is wrong?Show answer
The app almost certainly listens on 127.0.0.1 inside the container. Published traffic arrives on eth0, so make the app listen on 0.0.0.0.