A container has its own network namespace. A server listening on port 80 inside it is not listening on port 80 of the host. To reach it from the host, you publish the port.
The flag
docker run -d --name web -p 8080:80 nginx:1.27
│ │
│ └─ container port: where nginx listens
└────── host port: where clients connecthost container "web"
curl localhost:8080 ──► :8080 ──► :80 nginxDocker listens on host port 8080 and forwards each connection to port 80 inside the container.
Try it
docker run -d --name web -p 8080:80 nginx:1.27
docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e1dd94dc29ef nginx:1.27 "/docker-entrypoint.…" 2 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp webThe PORTS column reads 0.0.0.0:8080->80/tcp: every host address, port 8080, forwards to container port 80 over TCP.
curl -s localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...No -p, no host port
A container started without -p still runs its server, but the host has nothing on that port:
curl localhost:8081curl: (7) Failed to connect to localhost port 8081 after 0 ms: Couldn't connect to servercurl result | Meaning |
|---|---|
| Page returned | A container publishes the port and a server answers |
Couldn't connect to server | No container publishes this host port |
Read the mapping
docker port prints each published container port and the host address that forwards to it:
docker port web
80/tcp -> 0.0.0.0:8080docker port web 80 prints only the host side: 0.0.0.0:8080.
Mappings are fixed at creation
-p is a docker run (or docker create) option. There is no command to add or change a mapping on an existing container. Remove it and run it again:
docker rm -f web
docker run -d --name web -p 8081:80 nginx:1.27