Networking: port publishing and NAT
Publishing a port installs a NAT rule on the host. Understand the rewrite and every networking mystery gets smaller.
key idea / Docker itselfcontainer / good pathhost / watch outproblem / blockedneutral
The path of one request
Header rewriting in both directions
Container to container
Inside a Docker network you do not need publish rules at all.
Who can reach the port
| Flag | Reachable from | Note |
|---|---|---|
-p 8080:80 | any interface, including your LAN | same as 0.0.0.0:8080 |
-p 127.0.0.1:8080:80 | only this machine | safest for local development |
-p 80 | a random free host port | see it with docker port |
-P | every EXPOSEd port, random host ports | handy for quick tests |
Try it yourself
-
Step 1 · Publish the port and curl from the host
$ docker network create app $ docker run -d --name web --rm --network app -p 8080:80 nginx:1.27 $ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080 200 -
Step 2 · Read the published port
This mapping is a NAT rule on the host. The process inside still listens on port 80.
$ docker inspect -f '{{json .NetworkSettings.Ports}}' web {"80/tcp":[{"HostIp":"0.0.0.0","HostPort":"8080"}]} -
Step 3 · Another container does not use that host port
localhost:8080insideclientisclientitself. The namewebon port 80 is the container port, not the published one.$ docker run -d --name client --rm --network app alpine:3.20 sleep 300 $ docker exec client wget -q -O - http://localhost:8080 wget: can't connect to remote host: Connection refused $ docker exec client wget -q -S -O /dev/null http://web:80 HTTP/1.1 200 OK $ docker stop web client $ docker network rm app
Recap
-p host:containeradds a DNAT rule so host traffic on one port reaches the container on another.- Outbound traffic from containers is masqueraded behind the host IP.
- Containers on the same network talk by name and container port; never through published ports.
- Bind to
127.0.0.1to keep a published port off your LAN.
Quick check
Container
client runs curl localhost:8080 to reach web published as -p 8080:80, and it is refused. What should it call?Show answer
http://web:80 on a shared user-defined network. localhost is the client itself, and the published port exists on the host, not inside the network.