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. To do this, use -p <port in the host>:<port in the container>
when starting the container.
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
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.env
file.
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.