This error occurs when a Docker container cannot establish a network connection to a target host. It's typically caused by firewall rules blocking container traffic, incorrect network configuration, or the target host being unreachable from the container's network namespace.
The "dial tcp: connect: no route to host" error indicates that your Docker container is attempting to make a TCP connection to another host (either the Docker host, another container, or an external service) but the network layer is reporting that no route exists to reach the destination. This error is different from "connection refused" - a "no route to host" error means the network packets cannot even reach the destination, whereas "connection refused" means packets arrived but nothing was listening. This distinction is important for troubleshooting. This error commonly appears in several scenarios: - **Container-to-host communication**: A container trying to connect to a service running on the Docker host via the host's IP address - **Container-to-container communication**: One container trying to reach another container via published ports on the host IP - **Registry access**: Docker pull/push operations failing to reach a private registry in your network - **External service access**: Containers unable to reach external APIs, databases, or services - **CI/CD pipelines**: Build or test steps failing to connect to required services The root cause is almost always related to firewall configuration (especially firewalld on RHEL/CentOS/Fedora), Docker network configuration, or routing table issues.
The most common cause of this error on RHEL, CentOS, Fedora, and similar systems is firewalld blocking container traffic. Add masquerade support to allow Docker containers to communicate with the host:
# Enable masquerading for NAT from containers
sudo firewall-cmd --zone=public --add-masquerade --permanent
# Reload firewall to apply changes
sudo firewall-cmd --reload
# Restart Docker to re-establish network rules
sudo systemctl restart dockerVerify the masquerade is enabled:
sudo firewall-cmd --zone=public --query-masquerade
# Should output: yesThis single fix resolves the majority of "no route to host" issues on systems running firewalld.
If masquerade alone doesn't work, explicitly allow traffic from Docker's network subnets:
# Allow all Docker network traffic (172.x.x.x range)
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family=ipv4 source address=172.0.0.0/8 accept'
# Or specifically for the default bridge network (172.17.0.0/16)
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family=ipv4 source address=172.17.0.0/16 accept'
# Reload to apply
sudo firewall-cmd --reloadAlternative: Add docker0 interface to trusted zone:
sudo firewall-cmd --permanent --zone=trusted --change-interface=docker0
sudo firewall-cmd --reloadNote: If you're using custom Docker networks, they may use different subnets. Check your networks:
docker network inspect bridge | grep Subnet
docker network lsIf you need more granular control or firewalld's zone-based approach isn't working, use iptables directly:
# Allow all traffic from Docker's default bridge subnet
sudo iptables -I INPUT 1 -s 172.17.0.0/16 -j ACCEPT
# Or for a specific port only (e.g., port 8080)
sudo iptables -I INPUT 1 -s 172.17.0.0/16 -p tcp --dport 8080 -j ACCEPT
# Allow forwarding for Docker
sudo iptables -I FORWARD 1 -i docker0 -j ACCEPT
sudo iptables -I FORWARD 1 -o docker0 -j ACCEPTMake rules persistent (varies by distribution):
# On RHEL/CentOS
sudo service iptables save
# On Ubuntu/Debian
sudo apt install iptables-persistent
sudo netfilter-persistent saveCheck current iptables rules:
sudo iptables -L -n -v | head -50
sudo iptables -t nat -L -n -vMAC address conflicts between Docker networks can cause routing issues. If you're using docker-compose with multiple networks, try cleaning up:
# List all Docker networks
docker network ls
# Remove unused networks (keeps bridge, host, none)
docker network prune
# Or remove specific networks
docker network rm <network_name>Check for MAC address conflicts:
# List all MAC addresses across all networks
docker network inspect $(docker network ls -q) | grep -i macaddressFor docker-compose, bring down and recreate networks:
docker-compose down
docker-compose up -dIf the problem persists, try using a single network in your compose file instead of multiple custom networks.
Debug the network issue from inside the container to understand what's happening:
# Start a debug container with network tools
docker run --rm -it alpine sh
# Inside the container, install network tools
apk add --no-cache curl bind-tools iputils
# Test connectivity
ping -c 3 <target_ip> # ICMP test
nc -zv <target_ip> <port> # TCP port test
curl -v http://<target_ip>:<port> # HTTP test
nslookup <hostname> # DNS test
# Check routing table
ip routeFrom the host, verify the container's network:
# Find the container's IP
docker inspect <container_id> | grep IPAddress
# Test connectivity to container from host
ping <container_ip>If ping works but TCP fails, the issue is almost certainly firewall-related.
If you need a quick workaround while debugging, run the container with host networking to bypass Docker's network namespace:
# Run container with host network
docker run --network host <image>
# In docker-compose:
services:
myservice:
image: myimage
network_mode: hostImportant considerations:
- Host network mode removes network isolation between container and host
- Port conflicts can occur if container tries to bind to ports already in use
- This is a workaround, not a permanent solution
- Some features like port mapping (-p) don't work with host network mode
For testing purposes, this helps confirm whether the issue is network/firewall related.
If a container is trying to reach a service on the Docker host, ensure the service is listening on the right interface:
# Check what address the service is bound to
ss -tlnp | grep <port>
netstat -tlnp | grep <port>If the output shows 127.0.0.1:<port>, the service is only listening on localhost and won't be reachable from containers.
Fix by binding to all interfaces (0.0.0.0):
For common services:
PostgreSQL (/etc/postgresql/*/main/postgresql.conf):
listen_addresses = '*'MySQL (/etc/mysql/mysql.conf.d/mysqld.cnf):
bind-address = 0.0.0.0Redis (/etc/redis/redis.conf):
bind 0.0.0.0Node.js/Express:
app.listen(3000, '0.0.0.0', () => {});After changing the binding address, restart the service and ensure your firewall allows traffic to that port.
Instead of using the host's IP address, use Docker's built-in DNS names to reach the host:
Docker Desktop (Mac/Windows):
# Use this hostname to reach the Docker host
curl http://host.docker.internal:<port>Docker on Linux (20.10+):
# Add host-gateway to your container
docker run --add-host=host.docker.internal:host-gateway <image>
# In docker-compose:
services:
myservice:
extra_hosts:
- "host.docker.internal:host-gateway"Alternative: Use bridge gateway IP:
# Find the gateway IP (usually 172.17.0.1 for default bridge)
docker network inspect bridge | grep Gateway
# Use that IP to reach the host
curl http://172.17.0.1:<port>Using these methods is more reliable than hardcoding the host's network IP address.
Sometimes Docker's network state becomes inconsistent. A clean restart can resolve routing issues:
# Stop all containers gracefully
docker stop $(docker ps -q)
# Restart Docker daemon
sudo systemctl restart docker
# On systems without systemd
sudo service docker restart
# Verify Docker network rules are recreated
sudo iptables -L -n | grep -i docker
sudo iptables -t nat -L -n | grep -i dockerIf problems persist, try a full network cleanup:
# Stop Docker
sudo systemctl stop docker
# Remove Docker network interfaces (careful - this is disruptive)
sudo ip link delete docker0
# Restart Docker (it will recreate the interfaces)
sudo systemctl start docker
# Verify
ip addr show docker0Check Docker daemon logs for network errors:
sudo journalctl -u docker --since "10 minutes ago"Understanding Docker networking and firewalls:
Docker creates its own network infrastructure including bridge interfaces, iptables rules, and routing entries. When firewalld or iptables are running, they can interfere with Docker's networking in several ways:
- Zone processing order: firewalld processes zones by IP address before interface, which can cause unexpected behavior with Docker's bridge interface
- Masquerading: Docker containers need NAT to communicate with external networks. Without masquerade rules, outbound traffic appears to come from the container's private IP, which external hosts cannot route back to
Using firewalld direct rules:
When zone-based rules don't work reliably, firewalld direct rules are processed first and can be more effective:
# Direct rule to allow traffic on docker0 interface
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 10 -i docker0 -j ACCEPT
firewall-cmd --direct --permanent --add-rule ipv4 filter FORWARD 10 -i docker0 -j ACCEPT
firewall-cmd --reloadDiagnosing with packet tracing:
For complex network issues, trace packets through the system:
# Watch for dropped packets
sudo iptables -I INPUT -j LOG --log-prefix "IPTables-Dropped: "
sudo journalctl -f | grep IPTables
# Use tcpdump on docker0 interface
sudo tcpdump -i docker0 host <target_ip>
# Check conntrack state
sudo conntrack -L | grep <target_ip>SELinux considerations:
On systems with SELinux enforcing, container network access may be restricted:
# Check for SELinux denials
sudo ausearch -m avc -ts recent | grep docker
# Temporarily set to permissive to test
sudo setenforce 0
# If that fixes it, create proper policies rather than disabling SELinuxDocker compose network isolation:
When using docker-compose, containers on the same compose network can communicate by service name. For external access via published ports, firewall rules still apply:
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
backend:Containers on different networks cannot communicate directly unless they share a network, regardless of firewall configuration.
image operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub