A mapping on every interface
Reachable from the network even with a default-deny host firewall
8080:80
Resolve what each -p actually binds. The finding to read first is about the host firewall, because a published port is reachable whether or not ufw thinks it is.
Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.
The answer appears here
Paste on the left and press Test. Nothing leaves this tab.
Nothing else to flag.
No formatting problems, and nothing the rules object to. Worth remembering what that covers: this reads the file you pasted, not the account or cluster it will be applied to.
No finding matches that filter.
Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.
Reachable from the network even with a default-deny host firewall
8080:80
That is the container port, and the host side is chosen at random
80
Resolved at container start, and on an IPv6-first host that means IPv6 only
localhost:8080:80
These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
It binds every interface and Docker's rules are consulted before the host firewall's, so the port is reachable from the internet even with a default-deny policy.
Instead:Bind it: -p 127.0.0.1:5432:5432. If it must be reachable, put the restriction in the DOCKER-USER chain.
A single number is the container port. Docker assigns a random host port, which changes on every run.
Instead:Write 80:80.
EXPOSE is documentation. It opens nothing, so the container is not reachable until something passes -p or -P.
Instead:Publish with -p, and keep EXPOSE for describing the image.
Docker writes into the DOCKER chain of iptables, and that chain is consulted before the rules ufw and firewalld manage. A default-deny firewall does not stop a published port.
This surprises people because ufw status shows the port closed and the port is open. The forwarding happens in the nat table before the filter rules the firewall manages are reached. On a machine reachable from the internet, that is a database published to the internet by a command that looked local.
-p 127.0.0.1:8080:80 publishes to the loopback only, which is the right default for anything sitting behind a reverse proxy on the same host. Where a port genuinely must be public, rules belong in the DOCKER-USER chain, which Docker creates and never touches.
hostPort:containerPort. Reversing them is the commonest typo, and it usually produces a working container that nothing can reach, because the host side is a port nobody is trying.
-p 80 is the CONTAINER port, and Docker picks a random ephemeral host port for it. So the mapping changes on every run and docker port is the only way to find it. Almost nobody typing one number means that.
It records which ports an image listens on, for a human reading the Dockerfile and for -P. An image with EXPOSE 80 run without -p is not reachable, and an image with no EXPOSE publishes perfectly well with -p.
Docker resolves a hostname at container start. On a host where localhost resolves to ::1 first, the socket ends up on IPv6 only and an IPv4 client gets connection refused with nothing visibly wrong.