Docker Port Mapping Tester

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.

Paste below, or drop a file anywhere on this panel

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.

Examples

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.

A mapping on every interface

Reachable from the network even with a default-deny host firewall

8080:80

A single number

That is the container port, and the host side is chosen at random

80

localhost by name

Resolved at container start, and on an IPv6-first host that means IPv6 only

localhost:8080:80

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Publishing a database with -p 5432:5432 on a public host

    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.

  2. Writing -p 80 and expecting port 80 on the host

    A single number is the container port. Docker assigns a random host port, which changes on every run.

    Instead:Write 80:80.

  3. Relying on EXPOSE to publish a port

    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's rules sit in front of your firewall's

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.

A default-deny host still answers on every 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.

Bind explicitly and the problem disappears

-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.

The left of the colon is the host

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.

A single number is not the port you think

-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.

EXPOSE publishes nothing at all

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.

Use 127.0.0.1 rather than the name

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.