Skip to content

Publishing and Exposing Ports

There is a common source of confusion in Docker networking: the difference between EXPOSE in a Dockerfile and -p on docker run.

  • EXPOSE is 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.

The -p flag takes the form host_port:container_port:

Terminal window
docker run -p 8080:80 nginx:alpine

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

By default, Docker binds to all host interfaces (0.0.0.0). To restrict binding to the loopback interface only (no external access):

Terminal window
docker run -p 127.0.0.1:8080:80 nginx:alpine

This is useful for development environments where you want the service reachable only from the same machine.

Pass -p multiple times to publish more than one port:

Terminal window
docker run -p 8080:80 -p 8443:443 nginx:alpine

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:

Terminal window
docker port webserver

Output example:

80/tcp -> 0.0.0.0:8080

Let 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:

Terminal window
docker run -p 80 nginx:alpine

Docker picks a free port in the ephemeral range (typically 32768–60999). Use docker port to find out which port was assigned.

# 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
What does the EXPOSE instruction in a Dockerfile actually do?
You run: docker run -p 9000:3000 myapp. Which of the following correctly describes the port mapping?
How do you restrict a published port so it is only reachable from the local machine (loopback interface)?
Which command lists the port mappings of a running container named 'webserver'?