Run#
Here are some different options associated with running Docker containers.
Ports#
To be able to communicate with docker containers from outside the environment, you need to bind ports on the host to the ports on the container. In terms of docker this called ports publishing.
There are several options in docker run to specify the published ports:
The
-p <port in the host>:<port in the container>publishes the specified<port in the container>as some<port in the host>.The
-P,--publish-all: published all the ports that are exposed by the image.
The next cell starts the container with nc listening on port 999 port. At the same time container maps port 888 of the host to the port 999 of the container.
docker run -itd -p 888:999 --name port_example alpine sh -c "
apk update && apk add netcat-openbsd
nc -w 1 -l 0.0.0.0 999"
sleep 3 # wait some time to install netcat
9b38436b8510279cd380b59999b8f8517004753d955631fb9320be489a630415
The fact that container corresponds to port 888 on the host to the and port 999 on the container is displayed in the PORTS field of the docker ps command. The following cell shows it, and 888 -> 999 means that port 888 on the host corresponds to the port 999 on the host.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9b38436b8510 alpine "sh -c '\napk update …" 9 seconds ago Up 9 seconds 0.0.0.0:888->999/tcp, [::]:888->999/tcp port_example
The next code throws a message to the localhost 888.
echo "message to the conatiner" | nc localhost 888
The next cell shows the last line from the container logs - it corresponds to the message sent by the host.
docker logs port_example | tail -n 1
docker rm port_example &> /dev/null
message to the conatiner
Publish exposed#
To publish all ports that defined as exposed in the Docker image use the -P option of the docker run. This selects the host’s ports to be bound with the container ports, one by one, from the range of ports specified in the /proc/sys/net/ipv4/ip_local_port_range file.
The following cell runs the clickhouse container, which requires many ports to be exposed, and shows the output of the docker ps command.
docker run -d --rm -P --name all_ports clickhouse/clickhouse-server:25.3-alpine
docker ps
732c3956f2a1bff29a49e7a7124181f9c0abb46fc1d7a932a74630f9c917c8c6
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
732c3956f2a1 clickhouse/clickhouse-server:25.3-alpine "/entrypoint.sh" 1 second ago Up Less than a second 0.0.0.0:32786->8123/tcp, [::]:32786->8123/tcp, 0.0.0.0:32787->9000/tcp, [::]:32787->9000/tcp, 0.0.0.0:32788->9009/tcp, [::]:32788->9009/tcp all_ports
Five ports were exposed with just -P option.
docker stop all_ports
all_ports
The range of ports that Docker will attempt to use by default is displayed in the following cell.
cat /proc/sys/net/ipv4/ip_local_port_range
32768 60999
Environment variables#
Some tools’ configurations use environment variables, so if you are using such tools, you’ll need to pass environment variables to the container. There are two options in the docker run command that allow you to manage environment variables:
--env(-e): allows setting a variable and its value directly from the CLI. You should use the syntax-e <variable_name>=<value>.--env-file: allows loading variables from a specific.envfile.
The following cell shows the usage of the -e option — it creates a Docker container with the variable TOY_VARIABLE in it. As proof that the variable was actually created, its value was printed from the container.
docker run --rm -dit \
--name env_example \
-e TOY_VARIABLE="hello from toy variable" alpine &> /dev/null
docker exec env_example sh -c "echo \$TOY_VARIABLE"
docker stop env_example &> /dev/null
hello from toy variable
Now let’s try the same with variables defined in the .env file — just like in the following file:
cat << EOF > env_values
VAL1=10
VAL2="text value"
EOF
The following container loads the file we defined earlier and then displays the variables mentioned in the file — everything works well.
docker run --rm -dit \
--name env_file_example \
--env-file env_values \
alpine &> /dev/null
docker exec env_file_example sh -c "echo \$VAL1 \$VAL2"
docker stop env_file_example &> /dev/null
10 "text value"
Don’t forget to clean up the file that we used for the experiment.
rm env_values
Memory#
The -m option allows you to specify the memory limit for the container. For more detailed information, refer to the official documentation page.
The following example launches two containers: one with the default -m option and another with -m 1g. It then displays the output of the docker stats command.
docker run -itd --rm --name memory_full alpine &> /dev/null
docker run -itd --rm -m 1g --name memory_limit alpine &> /dev/null
docker stats --no-stream
docker stop memory_full memory_limit &> /dev/null
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c697ea033dd4 memory_limit 0.00% 500KiB / 1GiB 0.05% 266B / 0B 0B / 0B 1
b0c9337d2eb0 memory_full 0.00% 500KiB / 31.01GiB 0.00% 2.25kB / 0B 0B / 0B 1
Notice that in the MEM USAGE / LIMIT column for the memory_limit container, the value is 1GiB.
CPUs#
The --cpus option of the docker run command allows you to specify the number of CPU cores that will be allocated to the running Docker container.
As an example, consider an Alpine Docker container running the stress-ng --cpu 3 command, which forces the system to utilize 3 CPU cores.
The following cell runs this container without any restrictions on the number of CPUs it can utilize.
docker run -id --rm --name cpu_experiments alpine sh -c \
"apk update && apk add stress-ng && stress-ng --cpu 3" &> /dev/nbull
sleep 3
docker stats --no-stream
docker stop cpu_experiments &> /dev/null
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
a310ffc6534e cpu_experiments 301.56% 49.14MiB / 31.01GiB 0.15% 5.77MB / 75.6kB 0B / 0B 4
In the docker stats output, we observe 300% under the CPU column, indicating that all three CPU cores are being fully utilized.
Now, we’ll run a similar example, but with the key difference of using the --cpus 2 option in the docker run command.
docker run -id --rm --name cpu_experiments --cpus 2 alpine sh -c \
"apk update && apk add stress-ng && stress-ng --cpu 3" &> /dev/null
sleep 3
docker stats --no-stream
docker stop cpu_experiments &> /dev/null &> /dev/null
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
78c586383384 cpu_experiments 200.44% 49.13MiB / 31.01GiB 0.15% 5.86MB / 138kB 0B / 0B 4
Although stress-ng tries to use 3 CPU cores, in reality docker does not allow more than 2 cores.