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 -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.
Bind 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 -p 127.0.0.1:8080: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 -p 8080:80 -p 8443:443 nginx:alpineList 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:8080Let 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”# Run nginx with port 8080 on the host mapped to port 80 in the container
docker run -d -p 8080:80 --name webserver nginx:alpine
# Verify the port mapping
docker port webserver
# Test that the server is reachable
curl http://localhost:8080
# Cleanup
docker stop webserver && docker rm webserver