Objective
Publish a port with docker run -p 8080:80, then verify whether
the host firewall actually allows traffic from outside. The goal:
see the difference between “Docker claims the port is published”
and “external traffic can reach it”.
Tasks
Task 1: Start the container
docker run -d --name fw-test -p 8080:80 nginx:1.27
Task 2: Verify the listening socket
ss -tlnp | grep :8080
# LISTEN 0 4096 0.0.0.0:8080 0.0.0.0:* users:(("docker-proxy",pid=...,fd=4))
Task 3: Verify Docker’s DNAT rule
sudo iptables -t nat -L DOCKER -n -v | grep 8080
# Chain DOCKER (2 references)
# pkts bytes target prot opt in out source destination
# 0 0 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80
Task 4: Verify the host firewall
On a systemd host with nftables/ufw/firewalld, look for a rule that allows port 8080 inbound. Depending on the firewall:
# ufw
sudo ufw status | grep 8080
# firewalld
sudo firewall-cmd --list-all | grep 8080
# nftables
sudo nft list ruleset | grep 8080
Task 5: Probe from outside
If you have a second host on the same network:
# From the second host
curl -v http://docker-host:8080
If the host firewall blocks 8080, you get a connection refused or timeout at the network level — the docker-proxy is listening but no traffic reaches it.
Task 6: Reproduce the firewall block
Block the port and observe:
# ufw example
sudo ufw deny 8080
# Re-probe from outside; connection is refused
curl -v http://docker-host:8080
# Confirm with iptables
sudo iptables -L INPUT -n -v | grep 8080
# Restore
sudo ufw delete deny 8080
Task 7: Cleanup
docker rm -f fw-test