Practical Exercises for Docker Compose: Part 2

By Alwyn Botha, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud’s incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.

This set of tutorials focuses on giving you practical experience on using Docker Compose when working with containers on Alibaba Cloud Elastic Compute Service (ECS).

Part 1 of this series demonstrated several docker-compose configuration options that can be explored in isolation. In Part 2, we will look at several important docker-compose configurations including stop_grace_period, namespaced, ulimits, configs, and secrets.

Let’s get started.

stop_grace_period

From https://docs.docker.com/compose/compose-file/#stop_grace_period

By default, Docker waits 10 seconds for the container to exit before sending SIGKILL.

Specify how long to wait when attempting to stop a container if it doesn’t handle SIGTERM (or whatever stop signal has been specified with stop_signal), before sending SIGKILL.

Till now I did not have this setting ( stop_grace_period ) in my docker-compose files. Therefore I needed to specify -t 0 as seen below:

-t 0 specifies that docker-compose must wait zero seconds before killing the container — if it does not die gracefully in that time. The default value for that timeout is 10 seconds. So every time I do a docker-compose up I / we have to wait 10 seconds before it is finally killed and then brought back up again.

stop_grace_period in the docker-compose file allows us to specify our timeout = 0 value only there once off.

Add the following to your docker-compose.yml using

Run:

Make a minor change to the sleep timeout value, and rerun

Make another minor change to the sleep timeout value, and rerun

See how it gets recreated almost instantly every time.

Now change stop_grace_period to the default value of 10s.

Make a minor change to the sleep timeout value, and rerun

Make another minor change to the sleep timeout value, and rerun

See how the recreation takes 10 seconds each time.

If you look at the output of docker events you will see the details:

stop_grace_period: 0s

stop_grace_period: 10s

signal = 15

SIGTERM is the termination signal. Kill the process, but allow it to do its cleanup routines.

signal = 9

SIGKILL is the kill signal. Kill the process: immediately. The process cannot catch and process the signal on its own terms, it cannot cleanup.

Based on events output above, stop_grace_period: 0s waits 0.02 seconds from SIGTERM before it goes to SIGKILL.

Based on events output above, stop_grace_period: 10s waits 10+ seconds from SIGTERM before it goes to SIGKILL.

For the rest of these tutorials all the docker-compose files will contain: stop_grace_period: 0s

Note: you must determine an appropriate stop_grace_period for your production work environment. This will differ from one app to another.

sysctls

sysctls is used to set kernel parameters to set in the container.

What are kernel parameters?

Linux lets you set resource limits using kernel parameters. ulimit sets resource limits on a user level. Kernel parameters applies to everyone, root included.

You can check out the official reference information at https://www.kernel.org/doc/Documentation/sysctl/kernel.txt

Running man sysctl at Linux shell details how to configure kernel parameters at runtime.

Let’s start up our container again, using

Enter the container using:

Enter the following 3 commands at the prompt shown. It will show the current actual values for those 3 kernel parameters.

Expected output :

We are now going to modify those 3 values, and investigate the container to see if those values got applied.

Add the following to your docker-compose.yml using

Its content:

Run:

Enter the following 3 commands at the prompt shown. It will show the current NEW actual values for those 3 kernel parameters.

Expected output :

As you can see all 3 those kernel parms got changed.

You just experienced that Docker allows you to tune kernel parms on an individual container level.

From https://docs.docker.com/compose/compose-file/#sysctls

This option is ignored when deploying a stack in swarm mode with a (version 3) Compose file.

namespaced sysctls

( Continued from previous section, with important heading added )

From https://docs.docker.com/engine/reference/commandline/run/#configure-namespaced-kernel-parameters-sysctls-at-runtime

Important:

Not all sysctls are namespaced. Docker does not support changing
sysctls inside of a container that also modify the host system

CURRENTLY SUPPORTED SYSCTLS

kernel.msgmax, kernel.msgmnb, kernel.msgmni, kernel.sem,
kernel.shmall, kernel.shmmax, kernel.shmmni, kernel.shm_rmid_forced

Sysctls beginning with fs.mqueue.*

Sysctls beginning with net.*

This important text should be part of the https://docs.docker.com/compose/compose-file/#sysctls documentation.

I tried to change fs.file-max and got this error:

Now I understand: fs.file-max is not namespaced. Docker does not support changing sysctls inside of a container that also modify the HOST system

fs.file-max changes ( in the container ) would have changed that setting on the HOST server, which is not allowed.

Namespaces are a fundamental aspect of containers on Linux. Seehttps://en.wikipedia.org/wiki/Linux_namespaces

Namespaces are what allows a container to exist in its isolated bubble environment. Namespaces let containers think they are full Linux distros — running all alone on their servers.

fs.file-max is an example of a Linux feature that is not currently able to be namespace isolated in a container.

So non-namespaced kernel parameters must be tuned on the HOST server — to be appropriate for all the containers that run on it.

ulimits

Ulimit provides control over the resources ( such as sizes, cpu time, priorities) available to the shell and to processes started by it.

You can use it to ensure applications with bugs do not overload and crash your server.

In the context of Docker you can use it inside containers to similarly limit applications running inside containers.

Use man ulimit at shell prompt to read the official documentation about it — scroll to bottom to find ulimit.

Let’s prove that ulimits get enforced inside containers. Let’s set max number of processes and max number of open files absurd low and start up a container.

Add the following to your docker-compose.yml using

Try and start up the container:

Expected output :

As expected: too many open files error. Containers are tiny, but need more than 4 files open to start up.

Change the nproc ( number of processes to 1. Change both nofile limits to 40 or more.

Rerun:

It starts up perfect ( on my CentOS 7 server ).

Limiting nproc requires kernel 4.3 or higher — my server kernel version is 3.10.0–327.el7.x86_64. Get your kernel version by running uname -r.

Let’s set a ulimit that works: fsize — maximum filesize (KB)

Add the following to your docker-compose.yml using

Run:

Let’s exceed that file size limit of 10KB by creating a 10MB file:

The container just exists — my shell session crashed.

At some other time I got an error message :

configs

Configs declare configuration files for applications inside your containers need. Configuration files like those normally found inside /etc and F/opt.

You should only store non-sensitive information in these configs. docker-compose secrets are there to store secret information.

First we need to create a small 2 config files so that we can refer to it in our docker-compose.yml .

First we create the first config file:

Now create the second config file:

Now we need Docker to create this SECOND FILE ONLY as a config named: my_second_configF

These 2 different configs will demo 2 different ways configs can be used.

Add the following to your docker-compose.yml using

The top-level configs declaration ( bottom 5 lines) defines 2 configs that can be granted to the services in this stack.

The config at the service level ( around line 7 to 10 ) grants the container access to the 2 configs.

You must use both those config declarations.

Note that my_second_config is defined as: external: true. It exists as a config object in Docker.

docker-compose up does not support ‘configs’ configuration. We must use docker stack deploy to deploy to a swarm.

Expected output :

We have to run docker ps to get the automatically generated container name.

Now that we have that random generated container name we can enter it via exec: The random sequence for your container will be different. Use YOUR container name to exec into it.

Expected output :

Note that those configs are mounted in the / directory.

Let’s mount them in directories where Linux administrators would expect to find config.

Add the following to your docker-compose.yml using

Run:

Note the 2 different target paths: /etc and /opt.

Expected output :

Let’s enter our container and investigate if our configs are in the requested directories.

Expected output :

The ls confirms our configs are no longer in the / directory.

The 2 cat commands show our configs to be inside the requested directories.

secrets

Secrets work VERY similar to configs as explained above. The major difference is that the contents of secrets are encrypted.

Add the following to your docker-compose.yml using

Close down any existing stacks:

Let’s create my_secret:

The hyphen at the end means docker must read from stdin ( the echo text in this case ).

If you now run docker secret ls you will you have the secret listed.

We have to run docker ps to get the automatically generated container name.

Now that we have that random generated container name we can enter it via exec: The random sequence for your container will be different. Use YOUR container name to exec into it.

Run commands as shown:

If you run command below you will not see the secret itself:

To see a list of all secrets on your server, run

Reference:https://www.alibabacloud.com/blog/practical-exercises-for-docker-compose-part-2_594414?spm=a2c41.12532326.0.0

Follow me to keep abreast with the latest technology news, industry insights, and developer trends.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store