Overview and What You Will Learn
Most Docker networking failures come from five causes: containers on different networks, a name that does not resolve, an application listening on the wrong address, a host port conflict, and broken outbound routing or firewall rules. Each cause has one command that reveals it, so working through them in order usually finds the problem in minutes.
By the end of this lab you will be able to:
- Tell apart "connection refused", "timeout" and "name not resolved"
- Check network membership and name resolution from inside a container
- Find an application bound to
127.0.0.1instead of0.0.0.0 - Find what is holding a host port and free it
- Debug outbound internet failures and firewall interference
- Use a
netshootcontainer to inspect a network from the inside
Why This Matters in Production
Network problems look identical from the application: "cannot connect". Guessing wastes time and often makes things worse, for example by restarting healthy containers while the real fault is a missing network membership.
Imagine a new payment-api release that cannot reach postgres after a deploy. If the team restarts both containers three times before checking networks, the outage lasts longer than if one docker inspect had shown the API was attached to a different network. This scenario is illustrative, not a report of a specific incident.
Core Principles
What Each Error Tells You
The error message narrows the cause before you run anything. Read it first.
| Symptom | What It Usually Means |
|---|---|
bad address, Name or service not known |
Name does not resolve: wrong network, typo or default bridge |
Connection refused |
Host reached, but nothing is listening on that port or it is bound to loopback |
| Timeout or no route | Different networks, firewall rules or broken routing |
port is already allocated |
Another process or container holds the host port |
A Decision Path for Container-to-Container Failures
Check the layers in order: same network, name resolution, port reachable, application listening.
network and spelling"] D -->|Yes| F{"Port open?"} F -->|No| G["Check bind address
and app logs"] F -->|Yes| H["Check firewall
and app errors"] classDef start fill:#326CE5,color:#FFFFFF classDef check fill:#FFEDD5,color:#1E293B classDef fix fill:#D1FAE5,color:#1E293B class A start class B,D,F check class C,E,G,H fix
Detailed Step-by-Step Practical Lab
Step 1 - How to Set Up a Broken Environment to Practice On
Create two containers on different networks so you can see the real symptoms, then fix them.
docker network create frontend-netdocker network create backend-net docker run -d --name db --network backend-net \ -e POSTGRES_PASSWORD=mumbai-dev-secret postgres:16 docker run -d --name api --network frontend-net alpine:3.20 sleep 3600Step 2 - How to Check That Containers Share a Network
Containers can talk only when they share a network. List the networks each container has joined.
docker inspect api -f '{{range $name, $net := .NetworkSettings.Networks}}{{$name}} {{end}}'docker inspect db -f '{{range $name, $net := .NetworkSettings.Networks}}{{$name}} {{end}}' # backend-net # Fix: attach the api container to the database's networkdocker network connect backend-net apiA container can be attached to several networks, and it resolves names on every network it has joined.
Step 3 - How to Check Name Resolution
If the name does not resolve, look at the DNS server inside the container and confirm both containers are on a user-defined network.
docker exec api cat /etc/resolv.conf# nameserver 127.0.0.11 <- user-defined network, embedded DNS docker exec api nslookup db# Name: db# Address: 172.19.0.2If resolv.conf shows your host's DNS servers instead of 127.0.0.11, the container is on the default bridge, which has no name resolution. Recreate it on a user-defined network.
Step 4 - How to Test Whether a Port Is Reachable
Separate "the name works" from "the service answers". Test the container port, not the published host port.
docker exec api nc -zv db 5432# db (172.19.0.2:5432) open # For HTTP services, show the full exchangedocker exec api wget -S -O- http://payment-api:8080/healthIf a tool is missing in a slim image, use the netshoot container from Step 8 instead of installing tools into production images.
Step 5 - How to Fix "Connection Refused" Caused by the Bind Address
A server listening on 127.0.0.1 inside a container accepts connections only from that container. Other containers and published ports reach the container's network interface, so the server must listen on 0.0.0.0.
# See what the container is listening ondocker exec api netstat -tln# 127.0.0.1:8080 <- loopback only: unreachable from outside# 0.0.0.0:8080 <- all interfaces: reachableChange the application's host setting, for example HOST=0.0.0.0 or --bind 0.0.0.0:8080, and restart the container.
Common MistakePublishing a port with
-p 8080:8080while the app listens on127.0.0.1. Docker forwards the traffic correctly, but the application ignores it, and the browser shows a reset or empty response.
Step 6 - How to Fix "Port Is Already Allocated"
Only a running container or another host process can hold a host port. Find the owner, then stop it or choose another port.
# Which process on the host is using 8080?ss -tulpn | grep :8080 # Which running container publishes 8080?docker ps --filter publish=8080 --format "table {{.Names}}\t{{.Ports}}" # Stop the container, or map a different host portdocker stop old-apidocker run -d --name api -p 8081:8080 registry.razorpay.in/payment-api:v3.1.0Step 7 - How to Debug a Container With No Outbound Internet
Work outward: DNS first, then the route, then the host.
# 1. Does external DNS work?docker exec api nslookup api.stripe.com # 2. Can the container reach an IP directly?docker exec api wget -qO- --timeout=5 http://1.1.1.1 # 3. Can the host reach the internet?curl -I https://api.stripe.com # 4. Is IP forwarding enabled on the host?sysctl net.ipv4.ip_forward# net.ipv4.ip_forward = 1 # 5. Look at Docker's firewall chainssudo iptables -L FORWARD -n | headsudo iptables -L DOCKER-USER -nIf DNS fails but an IP works, the problem is the resolver, so check the host's DNS or the container's --dns setting. If both fail, look for host firewall rules, an internal: true network, or a VPN whose subnet overlaps Docker's 172.x range. Restarting Docker rebuilds its iptables rules, but it also stops running containers unless live-restore is enabled, so treat it as a last step.
SecurityPublished ports bypass some host firewall tools such as
ufwbecause Docker writes its own iptables rules. Restrict access with rules in theDOCKER-USERchain, or publish on a specific address like-p 127.0.0.1:5432:5432for services that should stay local.
Step 8 - How to Debug From Inside the Network With netshoot
nicolaka/netshoot is a container image packed with dig, curl, tcpdump, traceroute, iperf3 and more. Run it on the network under investigation, or share a specific container's network namespace.
docker pull nicolaka/netshoot # Join the same network as your servicesdocker run --rm -it --network backend-net nicolaka/netshoot # Or share the exact network namespace of the api containerdocker run --rm -it --network container:api nicolaka/netshoot # Inside netshootdig dbtcpdump -i eth0 port 5432traceroute dbSharing a container's namespace is the best way to debug a minimal image that has no shell or networking tools of its own.
Step 9 - How to Inspect a Network's Configuration
Check the subnet, gateway and attached containers when addresses look wrong or two networks overlap.
docker network lsdocker network inspect backend-net # Just the subnet and the attached containersdocker network inspect backend-net \ -f '{{range .IPAM.Config}}{{.Subnet}}{{end}} {{range .Containers}}{{.Name}} {{end}}'Production Best Practices & Common Pitfalls
- Diagnose before you restart. A restart does not fix a missing network, a wrong bind address or a port conflict.
- Test the container port, not the published one. Container-to-container traffic never uses
-pmappings. - Bind servers to
0.0.0.0in containers. Loopback-only listeners are the most common cause of "refused" errors. - Keep
netshootready. It is cheaper to attach a debug container than to rebuild a production image with extra tools. - Avoid subnet overlaps. Choose Docker network subnets that do not collide with your VPN or corporate ranges.
- Publish sensitive ports on loopback. Databases rarely need to be reachable from outside the host.
Quick Reference & Troubleshooting Commands
| Command | Description |
|---|---|
docker network ls |
List networks |
docker network inspect NET |
Subnet, gateway and attached containers |
docker network connect NET C |
Attach a running container to a network |
docker inspect C |
Full container configuration, including networks |
docker exec C nslookup NAME |
Test name resolution from the container |
docker exec C nc -zv HOST PORT |
Test whether a TCP port is open |
docker ps --filter publish=PORT |
Find the container publishing a host port |
docker run --rm -it --network container:C nicolaka/netshoot |
Debug inside a container's network namespace |
| Symptom | Likely Cause | Fix |
|---|---|---|
bad address for a container name |
Default bridge, typo or different network | Use one user-defined network |
Connection refused |
App not listening or bound to 127.0.0.1 |
Bind to 0.0.0.0 and check logs |
| Timeout between containers | Different networks or firewall | Connect to the same network, check rules |
port is already allocated |
Host port in use | Stop the owner or map another host port |
| No internet from container | DNS, forwarding or firewall problem | Follow Step 7 in order |
| Intermittent failures after restarts | Clients caching an old IP | Use names and fix client DNS caching |