Publishing and Exposing Ports
EXPOSE vs -p
Section titled “EXPOSE vs -p”There is a common source of confusion in Docker networking: the difference between EXPOSE in a Dockerfile and -p on docker run.
EXPOSEis documentation. It tells humans and tools which port the application listens on inside the container. It does not open any port or make anything reachable from outside.-p(or--publish) actually binds a host port to a container port. This is what makes traffic from outside the container reach your application.
If you only add EXPOSE 80 to your Dockerfile and forget -p, the application inside the container is listening, but nothing from the host or the internet can reach it.
Basic port publishing syntax
Section titled “Basic port publishing syntax”The -p flag takes the form host_port:container_port:
docker run -d --name webserver -p 8080:80 nginx:alpineThis binds port 8080 on the host to port 80 inside the container. A request to http://localhost:8080 on the host is forwarded to the container’s port 80.
List port mappings for a running container
Section titled “List port mappings for a running container”Use docker port to see all port bindings for a named container:
docker port webserverOutput example:
80/tcp -> 0.0.0.0:8080Test the published port
Section titled “Test the published port”Once published, the port is reachable from the host:
curl http://localhost:8080Bind to a specific host interface
Section titled “Bind to a specific host interface”By default, Docker binds to all host interfaces (0.0.0.0). To restrict binding to the loopback interface only (no external access):
docker run -d --name local-only -p 127.0.0.1:9090:80 nginx:alpineThis is useful for development environments where you want the service reachable only from the same machine.
Publish multiple ports
Section titled “Publish multiple ports”Pass -p multiple times to publish more than one port:
docker run -d --name multi -p 8080:80 -p 8443:443 nginx:alpineLet Docker pick the host port (ephemeral ports)
Section titled “Let Docker pick the host port (ephemeral ports)”Omit the host port to let Docker assign an available port automatically:
docker run -p 80 nginx:alpineDocker picks a free port in the ephemeral range (typically 32768–60999). Use docker port to find out which port was assigned.
Hands-on: publish and verify
Section titled “Hands-on: publish and verify”# Publish port 80 of nginx to host port 8080
docker run -d --name webserver -p 8080:80 nginx:alpine
# List port mappings
docker port webserver
# Curl the published port
curl http://localhost:8080
# Bind to loopback only
docker run -d --name local-only -p 127.0.0.1:9090:80 nginx:alpine
# Multiple ports
docker run -d --name multi -p 8080:80 -p 8443:443 nginx:alpine
# Cleanup
docker stop webserver local-only multi && docker rm webserver local-only multiTrade-offs
Section titled “Trade-offs”| Option | Benefit | Cost |
|---|---|---|
Publish to 0.0.0.0 (all interfaces) | Reachable from every machine on the network — good for a service that genuinely needs to be public | Opens access wider than necessary if the service should only be used locally |
Publish to 127.0.0.1 only | Restricts access to the same host — safer | Not reachable from any other machine on the network; needs a flag change to open it up later |
Common mistakes
Section titled “Common mistakes”- Assuming
EXPOSEin a Dockerfile actually publishes the port, when it is only documentation of which port the container listens on — only-p/--publishactually maps it so it can be reached. - Accidentally publishing to
0.0.0.0for a service that should only be reachable from localhost, like a database or an admin panel, exposing it to the network unnecessarily. - Publishing the same port from multiple containers on one host, causing
docker runto fail because another container already holds that port.
💡 Real-world example
A common deployment pattern publishes ports only from a single reverse proxy (such as Traefik or nginx) at
0.0.0.0:80and0.0.0.0:443, while every other backend service publishes no ports at all and talks over the internal network — leaving exactly one point exposed to the outside.