1. Overview

In Docker, it’s important to know which ports a containerized application is listening on. We also need a way to access the application from outside the container.

To address those concerns, Docker enables us to expose and publish the ports.

In this article, we’ll learn about both exposing and publishing ports. We’ll use a simple Nginx web server container as an example.

2. Exposing Ports

An exposed port is a piece of metadata about the containerized application. In most cases, this shows which ports the application is listening to. Docker itself does not do anything with an exposed port. However, when we launch a container, we can use this metadata when publishing the port.

2.1. Expose With Nginx

Let’s use the Nginx web server to try this out.

If we take a look at the Nginx official Dockerfile, we’ll see that port 80 is exposed with the following command:

EXPOSE 80

Port 80 is exposed here because it’s the default port for the http protocol. Let’s run the Nginx container on our local machine and see if we can access it through port 80:

$ docker run -d nginx

The above command will use Nginx’s latest image and run the container. We can double-check that the Nginx container is running with the command:

$ docker container ls

This command will output some information about all running containers, including Nginx:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
cbc2f10f787f        nginx               "/docker-entrypoint..."   15 seconds ago      Up 15 seconds       80/tcp              dazzling_mclean

Here we see 80 under the port section. Since port 80 is exposed, we might think that accessing localhost:80 (or just localhost) will display the Nginx default page, but that’s not the case:

$ curl http://localhost:8080
... no web page appears

Though the port is exposed, Docker has not opened it to the host.

2.2. Ways to Expose Ports

There are two main ways to expose ports in Docker. We can do it in the Dockerfile with the EXPOSE command:

EXPOSE 8765

Alternatively, we can also expose the port with the –expose option when running a container:

$ docker run --expose 8765 nginx

3. Publishing Ports

For a container port to be accessible through the docker host, we need to publish it.

3.1. Publish With Nginx

Let’s run Nginx with a mapped port:

$ docker run -d -p 8080:80 nginx

The above command will map port 8080 of the host to port 80 of the container. The general syntax for the option is:

-p <hostport>:<container port>

If we go to localhost:8080, we should get Nginx’s default welcome page:

$ curl http://localhost:8080
StatusCode : 200
StatusDescription : OK
Content : <!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
... more HTML

Let’s list all running containers:

$ docker container ls

Now we should see that the container has a port mapping:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
38cfed3c61ea        nginx               "/docker-entrypoint..."   31 seconds ago      Up 30 seconds       0.0.0.0:8080->80/tcp   dazzling_kowalevski

Under the ports section, we have the 0.0.0.0:8080->80/tcp mapping.

Docker, by default, added 0.0.0.0 non-routable meta-address for the host. It means that the mapping is valid for all addresses/interfaces of the host.

3.2. Restricting Container Access

We can restrict access to the container, based on the host IP address. Rather than allowing access to the container from all the interfaces (which 0.0.0.0 does), we can specify the host IP address within the mapping.

Let’s limit access to the container to traffic from just the 127.0.0.1 loopback address:

$ docker run -d -p 127.0.0.1:8081:80 nginx

In this case, the container is only accessible from the host itself. This uses the extended syntax for publishing, which includes an address binding:

-p <binding address>:<hostport>:<container port>

4. Publish All Exposed Ports

The exposed port metadata can be useful for launching a container as Docker gives us the ability to publish all exposed ports:

$ docker run -d --publish-all nginx

Here, Docker binds all exposed ports in the container to free random ports on the host.

Let’s look at the containers this command launches:

$ docker container ls

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
0a23e78732ce        nginx               "/docker-entrypoint..."   6 minutes ago       Up 6 minutes        0.0.0.0:32768->80/tcp   pedantic_curran

As we expected, Docker chose a random port (32768 in this case) from the host and mapped it to the exposed port.

5. Conclusion

In this article, we learned about exposing and publishing the ports in Docker.

We also discussed that the exposed port is metadata about the containerized application, whereas publishing a port is a way to access the application from the host.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.