Troubleshooting Docker Host Port Mapping Ignored on Bridge Network (Ubuntu 20.04 LTS)
Resolve Docker's host port mapping issues when containers on a bridge network fail to expose ports on Ubuntu 20.04 LTS. An expert SysAdmin guide.
Resolve Docker's host port mapping issues when containers on a bridge network fail to expose ports on Ubuntu 20.04 LTS. An expert SysAdmin guide.
Introduction
Deploying Docker containers with host port mappings (e.g., using the -p flag) is a fundamental aspect of container orchestration, allowing services running inside a container to be accessible from the host system and external networks. On Ubuntu 20.04 LTS, particularly when using the default bridge network, administrators occasionally encounter a perplexing issue where these crucial port mappings appear to be ignored. The containerized application runs perfectly fine internally, but attempts to reach it via the host's exposed port result in connection failures. This guide provides an in-depth, technical walkthrough to diagnose and resolve this specific Docker networking problem, focusing on iptables, firewall interactions, and core Linux network configurations.
Symptom & Error Signature
The primary symptom is that a Docker container configured with a host port mapping (e.g., -p 80:80) is not accessible on the specified host port. There isn't a direct Docker error message, but rather a failure to connect to the service from the host or external systems.
Consider an Nginx container mapped to host port 80:
docker run -d --name my-nginx -p 80:80 nginx:latest
Typical observations include:
Docker Reports Port Mapping as Active: The
docker psoutput indicates that Docker believes the port is mapped.docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b123abcd4567 nginx:latest "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp my-nginxThe
PORTScolumn showing0.0.0.0:80->80/tcpsuggests Docker has configured the mapping.Connection Refused or Timed Out from Host: Attempts to access the service via the host port fail.
curl http://localhost:80curl: (7) Failed to connect to localhost port 80: Connection refusedIf a firewall is actively blocking, it might present as a timeout:
curl: (7) Failed to connect to localhost port 80: Connection timed outHost Port Not Listening (or Not by Docker): Inspecting the host's listening ports (
netstatorss) does not show the expected Docker-mapped port, or it shows another service, but not the Docker container.sudo netstat -tulnp | grep :80(If working, you'd expect to see a line similar to
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -with Docker's process ID, or[...] LISTEN <docker-proxy-pid>/docker-proxy.) Often, this command returns no output related to Docker on port 80.Missing or Incorrect
iptablesRules: Docker extensively usesiptablesfor NAT and forwarding. If these rules are absent or corrupted, port mappings will fail.sudo iptables -t nat -L -n -v | grep DOCKER sudo iptables -L DOCKER -n -vYou might find the
DOCKERchain missing from thenattable, or specificDNATrules for your mapped port are absent.
Root Cause Analysis
The issue of Docker host port mappings being ignored on Ubuntu 20.04 LTS typically arises from conflicts or misconfigurations within the system's networking stack, primarily involving iptables. Common root causes include:
iptablesInterference from External Firewalls:- UFW Conflicts: Uncomplicated Firewall (UFW) is the most frequent cause on Ubuntu. Docker manages its own
iptablesrules. If UFW's default policies (especially for theFORWARDchain) are too restrictive (e.g.,DROP), or if UFW operations (likeufw reload) flush or reorder rules without proper Docker integration, Docker's NAT and forwarding rules can be bypassed or deleted. - Manual
iptablesManagement: Customiptablesscripts or other firewall daemons (firewalld,nftablesdirectly) can clash with Docker's rule management. iptablesBackend Issues: While Ubuntu 20.04 usesnf_tablesas its defaultiptablesbackend, Docker might still preferlegacymode. Mismatches or misconfigurations can lead to rule application failures.
- UFW Conflicts: Uncomplicated Firewall (UFW) is the most frequent cause on Ubuntu. Docker manages its own
ip_forwardDisabled: The Linux kernel'snet.ipv4.ip_forwardparameter must be enabled (1) for packets to be routed between different network interfaces (e.g., from your host's primary interface to thedocker0bridge). If this is disabled, Docker cannot forward traffic to containers.Docker Daemon
iptablesDisablement: A misconfigured/etc/docker/daemon.jsonfile explicitly setting"iptables": falsewill prevent Docker from generating and managing the necessaryiptablesrules for port forwarding.NetworkManager Interference: Although less common,
NetworkManagercan, in rare scenarios, attempt to manage thedocker0bridge interface, leading to unexpected network behavior and rule conflicts.Container Application Listening Address: The application inside the container might be bound only to its loopback interface (
127.0.0.1) instead of listening on0.0.0.0(all interfaces). If the application isn't listening on0.0.0.0inside the container, Docker's port mapping, which targets the container's bridge IP, will fail to establish a connection.Stale Docker Network Configurations: Occasionally, a Docker daemon restart or system reboot might not properly re-establish all
iptablesrules, especially after system updates or unexpected shutdowns.
Step-by-Step Resolution
Follow these steps systematically to diagnose and resolve the port mapping issue. Always test your Docker container's accessibility after each major change.
1. Verify ip_forward Status
Ensure that IP forwarding is enabled, as it's fundamental for Docker's NAT and routing capabilities.
sysctl net.ipv4.ip_forward
If the output is net.ipv4.ip_forward = 0, enable it:
echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-sysctl.conf
sudo sysctl -p /etc/sysctl.d/99-sysctl.conf
Enabling
ip_forwardallows your system to route packets between network interfaces. While essential for Docker, ensure your firewall rules are robust, especially on internet-facing servers, to prevent unintended network exposure.
2. Inspect Docker Daemon Configuration
Check Docker's main configuration file for explicit iptables disabling.
cat /etc/docker/daemon.json
Look for a line "iptables": false. If present, remove it or change it to "iptables": true. If the file doesn't exist or is empty, Docker defaults to iptables integration, which is desired.
Example of problematic daemon.json:
{
"iptables": false,
"log-driver": "json-file"
}
If you modify daemon.json, you must restart the Docker daemon:
sudo systemctl restart docker
sudo systemctl status docker
3. Address UFW (Uncomplicated Firewall) Conflicts
UFW is the most common disruptor of Docker port mappings on Ubuntu. Docker's iptables rules often need to be processed before UFW's general policies take effect.
The following steps involve modifying UFW configurations or temporarily disabling it. Proceed cautiously, especially on production systems, as this might briefly alter network security.
Option A: Temporarily Disable UFW (for rapid diagnosis)
This quickly determines if UFW is the root cause.
sudo ufw disable
sudo systemctl restart docker
# Stop and restart your container to ensure rules are reapplied
docker stop my-nginx && docker rm my-nginx
docker run -d --name my-nginx -p 80:80 nginx:latest
# Test accessibility
curl http://localhost:80
If the port mapping now works, UFW is the culprit. Re-enable UFW with sudo ufw enable and proceed to Option B for a permanent solution.
Option B: Configure UFW for Docker Integration (Recommended)
Modify UFW's rule files to accommodate Docker's iptables management.
Edit
ufw before.rules: Open/etc/ufw/before.rulesin a text editor:sudo nano /etc/ufw/before.rulesNavigate to the
*filtersection. Before the line-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT, add the following rules to permit Docker-related forwarding:# START DOCKER UFW RULES -A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A ufw-before-forward -i docker0 -j ACCEPT -A ufw-before-forward -o docker0 -j ACCEPT # Allow traffic from/to docker containers (adjust if your bridge network is not default) -A ufw-before-forward -s 172.17.0.0/16 -j ACCEPT -A ufw-before-forward -d 172.17.0.0/16 -j ACCEPT # END DOCKER UFW RULESNext, go to the
*natsection. Before anyMASQUERADErules (e.g.,-A POSTROUTING -s 192.168.0.0/16 -o eth0 -j MASQUERADE), add rules for Docker's NAT. You may need to inspect your Docker bridge network for its exact subnet usingdocker network inspect bridge. The default is172.17.0.0/16.# START DOCKER NAT RULES *nat :POSTROUTING ACCEPT [0:0] # Allow Docker to masquerade traffic from its bridge network -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE # END DOCKER NAT RULESReplace
172.17.0.0/16with your actual Docker bridge network subnet if it differs. You can find this withdocker network inspect bridgeand looking forSubnetunderIPAM.Config.Modify UFW Default Forward Policy (if restrictive): If your
ufwdefaultFORWARDpolicy isDENYorDROP, this can override Docker's rules. Check your policy with:sudo ufw status verbose | grep "Default:"If it states
Default: deny (forward), you have two options:- Change the default in
/etc/default/ufw: SetDEFAULT_FORWARD_POLICY="ACCEPT". (Requiressudo ufw reload). - Add specific UFW rules to allow forwarding for Docker:
sudo ufw route allow in on docker0 from any to any(and similar forout on docker0). This is generally handled by thebefore.rulesmodifications.
- Change the default in
Restart UFW and Docker:
sudo ufw reload sudo systemctl restart docker # Re-create and test your container docker stop my-nginx && docker rm my-nginx docker run -d --name my-nginx -p 80:80 nginx:latest curl http://localhost:80
4. Manually Inspect iptables Rules
After addressing ip_forward, daemon.json, and UFW, verify that Docker's iptables rules are correctly instantiated.
# Check NAT table for DOCKER chain and DNAT rules
sudo iptables -t nat -L -n -v | grep -E 'DOCKER|DNAT'
# Expected output should include:
# Chain DOCKER (1 references)
# DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
# Check the FILTER table for DOCKER chain rules
sudo iptables -L DOCKER -n -v
# Expected output will show ACCEPT rules for forwarded traffic
# Check the DOCKER-USER chain (if you've added custom iptables rules)
sudo iptables -L DOCKER-USER -n -v
If these critical rules are missing after restarting Docker and UFW, try a full system reboot as a last resort to ensure a clean iptables slate.
5. Verify Container Application Listening Address
Confirm that the application inside your Docker container is listening on 0.0.0.0 (all interfaces) and not just 127.0.0.1 (localhost within the container).
Get Container IP Address:
docker inspect -f '{{.NetworkSettings.IPAddress}}' my-nginx(Example output:
172.17.0.2)Execute
netstat(orss) inside the Container:docker exec my-nginx netstat -tulnp | grep :80For most web servers (like Nginx), you should see it listening on
0.0.0.0:80:tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginxIf it shows
127.0.0.1:80, the application is not configured to accept connections from other interfaces within the container, preventing Docker's port mapping from reaching it. You would need to reconfigure the application within the container image to listen on0.0.0.0.
6. Recreate Docker Container and Restart Docker Service
Sometimes, lingering network configurations or iptables issues can be resolved with a clean restart and container recreation.
# Stop and remove the problematic container
docker stop my-nginx
docker rm my-nginx
# Restart Docker service
sudo systemctl restart docker
# Verify Docker service is running and healthy
sudo systemctl status docker
# Relaunch your container with the port mapping
docker run -d --name my-nginx -p 80:80 nginx:latest
# Test accessibility
curl http://localhost:80
7. Check for NetworkManager Interference (Advanced/Rare)
While NetworkManager usually ignores docker0, in specific configurations, it might interfere. You can explicitly instruct NetworkManager to ignore the docker0 bridge.
- Create a configuration file:
sudo nano /etc/NetworkManager/conf.d/docker-bridge.conf - Add the following content:
[keyfile] unmanaged-devices=interface-name:docker0 - Restart
NetworkManager(this will temporarily disrupt network connectivity):
Aftersudo systemctl restart NetworkManagerNetworkManagerrestarts, restart Docker and retest your container.
By systematically applying these expert-level troubleshooting steps, you can effectively diagnose and resolve persistent Docker host port mapping issues on your Ubuntu 20.04 LTS systems, restoring expected network accessibility for your containerized services.
Our Production Verification Guarantee
Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.