Introduction
Docker container network failures manifest in many ways: containers cannot reach external services, cannot communicate with each other, or are unreachable from outside the host. Unlike application errors, network issues often have no clear error message—connections simply hang or timeout. The root cause spans Docker networking, host firewall rules, DNS configuration, and routing.
Docker uses several network drivers (bridge, host, overlay, macvlan), but the default bridge network is most common. Understanding how Docker configures NAT, DNS, and virtual interfaces is essential for debugging.
Symptoms
- Container cannot ping external hosts (google.com, 8.8.8.8)
- Container DNS resolution fails or times out
- Containers on same host cannot communicate
- Port mapping doesn't work (localhost:8080 doesn't reach container)
- Container can reach some hosts but not others (MTU issues)
- Network errors:
getsockopt: connection refused,i/o timeout,temporary failure in name resolution
Common Causes
- **DNS misconfiguration**: Container cannot resolve hostnames
- **Bridge network broken**: Docker bridge (docker0) is down or misconfigured
- **IPtables rules**: Host firewall blocks Docker traffic
- **Port conflict**: Host port already in use, mapping fails silently
- **MTU mismatch**: Large packets dropped, causing intermittent failures
- **Overlay network issues**: Swarm/Compose overlay networks not syncing
- **Host network namespace**: Container isolated from host network
- **Docker daemon crashed**: Docker networking service stopped
Step-by-Step Fix
### 1. Check container network configuration
```bash # Inspect container network settings docker inspect <container-id> --format='{{json .NetworkSettings}}' | jq
# Check assigned IP address docker inspect <container-id> --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
# List all networks docker network ls
# Inspect specific network docker network inspect bridge ```
### 2. Test DNS resolution inside container
```bash # Run a test container docker run --rm -it alpine sh
# Test DNS resolution nslookup google.com ping -c 3 8.8.8.8 ping -c 3 google.com ```
If 8.8.8.8 works but google.com doesn't, it's a DNS issue.
**Fix DNS configuration:**
```bash # Option 1: Set DNS in Docker daemon config # /etc/docker/daemon.json { "dns": ["8.8.8.8", "8.8.4.4"] } # Then restart Docker sudo systemctl restart docker
# Option 2: Set DNS per container docker run --dns 8.8.8.8 --dns 8.8.4.4 <image>
# Option 3: Use host DNS docker run --dns-opt "options:rotate" <image> ```
### 3. Check Docker bridge interface
```bash # Check docker0 bridge exists ip addr show docker0
# Check bridge is UP ip link show docker0
# Check NAT masquerading iptables -t nat -L POSTROUTING -n | grep MASQUERADE ```
If docker0 is missing or DOWN:
```bash # Restart Docker to recreate bridge sudo systemctl restart docker
# Verify bridge created ip addr show docker0 # Should show: inet 172.17.0.1/16 scope global docker0 ```
### 4. Check iptables rules
Docker modifies iptables for NAT and port forwarding. If rules are flushed, networking breaks:
```bash # Check Docker chains exist iptables -L DOCKER -n iptables -t nat -L DOCKER -n
# Check NAT rules iptables -t nat -L -n | grep -E "DOCKER|MASQUERADE" ```
**Fix: Restart Docker to recreate rules**
bash
sudo systemctl restart docker
**Fix: Flush and recreate (if rules are corrupted)**
```bash # Stop Docker sudo systemctl stop docker
# Flush iptables iptables -t nat -F iptables -t mangle -F
# Start Docker (recreates rules) sudo systemctl start docker ```
### 5. Test container-to-container communication
```bash # Create a test network docker network create test-net
# Run two containers docker run -d --name c1 --network test-net alpine sleep 3600 docker run -d --name c2 --network test-net alpine sleep 3600
# Test connectivity from c1 to c2 docker exec c1 ping -c 3 c2 docker exec c1 ping -c 3 172.18.0.2 # c2's IP ```
If ping fails:
- Check network driver: docker network inspect test-net
- Check container firewalls (ufw, firewalld)
- Check if inter-container communication is disabled
**Fix ICC (Inter-Container Communication):**
```bash # Check daemon.json cat /etc/docker/daemon.json # If "icc": false is set, containers cannot communicate
# Fix: Enable ICC or use user-defined networks { "icc": true } ```
### 6. Check port mapping
```bash # Check port bindings docker port <container-id>
# Test from host curl localhost:<port> telnet localhost <port> nc -zv localhost <port>
# Test from outside (different host) curl <host-ip>:<port> ```
If port mapping doesn't work:
```bash # Check if port is already in use netstat -tlnp | grep <port> ss -tlnp | grep <port> lsof -i :<port>
# Check firewall allows the port sudo ufw status sudo firewall-cmd --list-all ```
### 7. Check MTU issues
MTU mismatch causes large packets to be dropped, resulting in intermittent connectivity:
```bash # Check host MTU ip link show docker0 | grep mtu
# Check container MTU docker exec <container> ip link show eth0 | grep mtu
# Test with different packet sizes ping -s 1472 -M do google.com # Should work ping -s 1473 -M do google.com # May fail if MTU too high ```
**Fix MTU mismatch:**
bash
# Set MTU in daemon.json
{
"mtu": 1450
}
# Restart Docker
sudo systemctl restart docker
Common MTU values: - Standard Ethernet: 1500 - Docker overlay: 1450 - AWS VPC: 9001 (jumbo frames) or 1500
### 8. Check overlay networks (Swarm/Compose)
For multi-host networks:
```bash # Check overlay network docker network inspect <overlay-net>
# Check Swarm network status docker service ls docker network ls
# Check encryption keys ls -la /var/lib/docker/swarm/ ```
If overlay networks broken:
- Verify Swarm is initialized: docker node ls
- Check gossip port (7946) open between nodes
- Check VXLAN port (4789) open between nodes
### 9. Restart Docker networking
As a last resort, restart all networking:
```bash # Restart Docker sudo systemctl restart docker
# Prune unused networks docker network prune -f
# Remove and recreate custom networks docker network rm broken-net docker network create --driver bridge broken-net ```
Debugging Commands Summary
```bash # Container network info docker inspect <container> --format='{{json .NetworkSettings}}' | jq
# DNS test in container docker run --rm alpine nslookup google.com
# Bridge status ip addr show docker0
# NAT rules iptables -t nat -L -n | grep DOCKER
# Port mapping docker port <container> netstat -tlnp | grep <port>
# MTU check ip link show docker0 | grep mtu
# Network list docker network ls docker network inspect bridge ```
Prevention Checklist
- [ ] Use user-defined bridge networks for container isolation
- [ ] Set explicit DNS servers in daemon.json
- [ ] Document port mappings in docker-compose.yml
- [ ] Test network connectivity in CI/CD pipeline
- [ ] Monitor Docker network metrics (dropped packets, errors)
- [ ] Use health checks that verify network connectivity
- [ ] Keep Docker version updated for network bug fixes
- [ ] Configure MTU consistently across hosts and networks
Related Issues
- [Fix Docker DNS Resolution Failing](/articles/fix-docker-dns-not-working)
- [Fix Docker Container Exit Code 137](/articles/fix-docker-container-exited-code-137)
- [Fix Kubernetes Pod Network Issues](/articles/fix-kubernetes-cni-not-working)
- [Fix Port Already in Use](/articles/fix-port-already-in-use)