Docker Course Labs

Constructing the Container Environment

Docker creates the virtual environment for a container. You can specify how parts of the environment should be set, which lets you prepare the container for your applications.

CLI Reference

Container environments are static - the details are fixed for the life of the container. You configure the environment in the docker run command:

There are dozens of options for running a container:

docker run --help

The arguments we'll use here are:

Environment variables

Environment variables are key-value pairs set in the OS. Applications can read them and they're often used for configuration settings.

printenv is the Linux command to print them all:

docker run alpine printenv

docker run openjdk:8-jre-alpine printenv

You'll see variables set by the OS and in the container package.

📋 Run a new container - set your own environment variable and print all the variables.

# -e adds a new environment variable
docker run -e COURSELABS=env alpine printenv

Environment variables can't be edited, they're set for the lifetime of container.

You can add as many environment variables as you need, and you can also override default variables for the container:

docker run -e COURSELABS=env -e LANG=C.UTF-16 openjdk:8-jre-alpine printenv

This overrides the default language setting in the Java container.

If you're setting lots of variables, it's easier to store them all in a file like exercises.env and pass that to the container as an environment file.

📋 Run container loading labs/env/exercises.env as an environment file.

# check the contents of the local file:
cat labs/env/exercises.env

# run a container loading that file as environment variables:
docker run --env-file labs/env/exercises.env alpine printenv

Env file contents overwrite default values, but you can overwrite them too using -e flags

Container filesystem

Containers filesystems are virtual disks, put together by Docker. Every container starts with the disk contents set up in the container package.

📋 Run a background Nginx container called nginx.

# alpine is the smallest variant but any will do:
docker run -d --name nginx nginx:alpine

You can connect to a detached container and run commands in it - useful for exploring the filesystem:

docker exec -it nginx sh

ls /usr/share/nginx/html/

cat /usr/share/nginx/html/index.html

exit

The container has the Nginx web server installed, and some default HTML pages.

You can mount a directory from your local machine into the container filesystem. You can use that to add new content, or to override existing files.

Run a container to show the new web page - you need to use the full path as the source for the volume:

# put the full local path in a variable - on macOS/Linux:
htmlPath="${PWD}/labs/env/html"

# OR with PowerShell:
$htmlPath="${PWD}/labs/env/html"

# run a container mounting the local volume to the HTML directory:
docker run -d -p 8081:80 -v ${htmlPath}:/usr/share/nginx/html --name nginx2 nginx:alpine

Browse to http://localhost:8081 and you'll see the custom HTML response.

The container is reading data from your local machine. You can edit index.html and when you refresh your browser you'll see your changes straight away.

Compute resources

You can restrict the amount of compute power containers have. By default there's no restriction, so the container sees all the CPUs and memory your machine has.

Run a compute-intensive app without restrictions:

docker run -d -p 8031:80 --name pi kiamol/ch05-pi -m web 

Browse to http://localhost:8031/pi?dp=50000 - this calculates Pi to 50K decimal places. On my machine that takes ~3s.

You can't change CPU resources for a container, they're fixed like the other environment setup.

📋 Inspect the details of the container to see the complete configuration.

docker inspect pi

All CPU and memory quotas are set to 0, meaning they're not restricted.

Try running a the same app in a container with only 200Mb of memory and 1/4 of a CPU core:

docker rm -f pi

docker run -d -p 8031:80 --name pi --memory 200m --cpus 0.25 kiamol/ch05-pi -m web 

Refresh http://localhost:8031/pi?dp=50000 and it will take much longer - over 13s on my machine

You can print specific parts of the container configuration using formatting:

docker container inspect --format='Memory: b, CPU: n' pi

Memory is returned in bytes, and CPU as nano-cores (1-billionth of a core!).

Lab

We ran a container to generate TLS certificates in the containers lab, but the certs were created inside the container filesystem.

In this lab your job is to copy the TLS certificate and key from the container onto your local machine.

Start by generating certs in a new named container - run it in the background and the container will stay up:

docker run -d --name tls kiamol/ch15-cert-generator

Now copy the server-cert.pem and server-key.pem files from the /certs folder in the container onto your machine.

Stuck? Try hints or check the solution.


Cleanup

Cleanup by removing all containers:

docker rm -f $(docker ps -aq)