Port publishing
Outline
In this chapter you will learn:
- Why do we need to publish container ports.
- How to publish container ports.
Walkthrough
By default containers do not publish any ports to the outside world. Ports are opened only for internal container-to-container or host-to-container communication in a Docker network. In order to access container ports from the outside of the Docker network, e.g. via public host IP or host loopback address, ports must be published explicitly via docker run
command.
Task 1: Why do we need publish container ports
The objective of this task is to ilustrate the problem of publishing ports in containers.
Let's run a container with Nginx:
$ docker run --name noportpub -d --rm nginx
List the created container:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dc8defc10363 nginx "nginx -g 'daemon of…" 11 seconds ago Up 9 seconds 80/tcp noportpub
Analyze the command output.
Note that the container exposes port 80
for internal HTTP
communication (PORTS
column).
Now, fetch the IP of the container in the Docker network:
$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' noportpub
172.18.0.2
Try to communicate with the Nginx server using obtained internal container IP:
$ curl http://172.18.0.2:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
...
The communication succeeds and Nginx server responds with a welcome message. This is because the communication happend in the scope of the internal Docker network.
Subsequently, let's try to communicate with the server via loopback address which is an address from the outside of the Docker network:
$ curl http://localhost:80
curl: (7) Failed to connect to localhost port 80: Connection refused
The connection has been refused, because default firewall rules prevent communication with port 80
in the container from the outside of the Docker network.
Task 2: Publishing container ports
In order to publish a container port there is --publish
flag for docker run
command. It has the following syntax:
--publish HOST_PORT:CONTAINER_PORT
It defines a mapping between HOST_PORT
and CONTAINER_PORT
. Multiple instances of this option can be provided to define mapping for multiple container ports.
As an example, let's run a container with Nginx and publish port 80
to the outside:
$ docker run --name portpub -d --rm --publish 8080:80 nginx
We've mapped port 8080
of the Docker host to port 80
of the container. This means, that all communication to port 8080
on the host will be forwarded to port 80
in the container. Also, appropriate firewall rules are set to permit the communication.
Once again try to communicate with the Nginx server from the Docker host:
$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
...
This time the communication succeed. You may also try to access Nginx via the web browser by entering the same URL.
Exercises
- Run a
Redis
container with port6379
exposed to the outside - map port6000
of the Docker host to port6379
of the container. Connect to containerized Redis instance via loopback address and try to set several keys:
$ redis-cli -h localhost -p 6000