Reported symptoms
docker psshows the container is running and healthy.- From inside the host,
curl localhost:8080returns the application. - From outside the host, the connection is refused or times out.
sudo ufw statusshows the host firewall is off or has no rule for 8080.
Evidence provided
$ ss -tlnp | grep 8080
LISTEN 0 4096 0.0.0.0:8080 ... users:(("docker-proxy",...))
$ sudo iptables -t nat -L DOCKER -n -v
Chain DOCKER (1 references)
pkts bytes target prot opt in out source destination
12 720 DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:8080
$ sudo nft list ruleset | grep -A 1 'chain input'
chain input {
type filter hook input priority 0; policy drop;
}
The docker-proxy is bound, the DNAT rule is in place, but the default-DROP policy on the FORWARD path (or the bridge’s no-track path) is killing the packet before it reaches the container.
Resolution path
- Confirm the packet reaches the host.
tcpdump -i any -n port 8080while reproducing. If no SYN ever shows up at the wire, the issue is upstream of the host (routing, ISP, peer).- Confirm the host accepts the packet on the FORWARD path.
- If the packet arrives but no SYN-ACK leaves, the host is dropping it.
nft list rulesetand look at FORWARD;iptables -L FORWARD -n -vis the iptables equivalent. - Add the allow rule to DOCKER-USER, not INPUT.
- DOCKER-USER is the operator-owned chain in the FORWARD path that Docker creates. Rules there apply to traffic on its way to a published port.
sudo nft add rule ip filter DOCKER-USER iifname "eth0" tcp dport 8080 accept- Verify by probing from outside the host.
- A second host on the same network is the right test.
curl http://docker-host:8080. From the host itself, the firewall is bypassed and the test is meaningless. - For ufw specifically: recognise that ufw INPUT rules do not apply here.
- ufw manages the INPUT chain by default. Published ports never see INPUT. Either reconfigure ufw to manage DOCKER-USER too (
DEFAULT_FORWARD_POLICYin/etc/default/ufw, the manual DOCKER-USER hook in/etc/ufw/after.rules), or use nftables directly.
Verification
- curl from a second host succeeds.
- The application responds with the expected payload.
- The DOCKER-USER counter increments.
nft list rulesetafter the test connection shows the rule has matched.- The INPUT counter does not increment for traffic to the published port.
- This is the expected behaviour: published-port traffic bypasses INPUT.