Setting up Docker containers with docker run is straightforward, but if you need the same kind of containers over and over again, there is an even more convenient way: the docker compose command.
The docker compose command evaluates the docker-compose.yml text file in the current directory and then sets up the appropriate containers. This is especially useful if you want to combine multiple containers in one setup.
To use docker compose, you just need to learn the syntax of docker-compose.yml. This is the syntax we’ll focus on in this post.
In the past, docker-compose was a command independent of docker. In current versions, however, compose is implemented as a subcommand of docker and can thus be called without a hyphen. In Spring 2022, the new docker compose command was built in to Docker Desktop by default. Linux users with older Docker installations, on the other hand, had to install the old docker-compose command separately.
Regarding their functionality, docker-compose and docker compose are almost completely identical (see also the following link with a very short list of incompatibilities). What has changed, however, is the internal implementation: like the entire docker command, docker compose was developed in the Go programming language and should run noticeably faster than the older docker-compose command, which is actually a Python script.
https://docs.docker.com/compose/cli-command-compatibility
Docker-Compose Versus Docker Stack
As if the differentiation between docker compose and docker-compose wasn’t enough, docker stack opens up another way to bring a setup formulated in docker-compose.yml to life, so to speak:
- The traditional way is to use the docker compose or docker-compose command to set up and start the containers.
- Alternatively, you can use docker stack deploy to create and run equivalent services. Just as docker compose saves you from running docker run or docker exec multiple times with countless parameters, docker stack deploy replaces various commands of the docker service ...
Although the end result is ultimately very similar (you can use the setup described in the file), the differences behind the scenes are significant: docker compose works directly with containers.
docker stack deploy, on the other hand, sets up a group (a stack) of services. Services were designed to make Docker services distributable and scalable. However, you absolutely don’t need to set up a Docker cluster (or swarm, to stick with the official terminology) for you to use docker stack deploy. It suffices to run docker swarm init once, which turns your Docker instance into a mini swarm consisting of just one member.
So, the initial hurdle for docker stack deploy isn’t high. Nevertheless, you must be aware that the use of services brings an additional layer of abstraction into play. For Docker beginners, this makes the application more confusing without providing any immediate benefits. In this respect, it’s advisable, especially for beginners, to give preference to docker compose for the time being.
Advanced Docker users, on the other hand, consider services to be the better containers. “Docker service is the new docker run,” was once said at a Docker talk. docker stack deploy is then the more versatile alternative to docker compose.
docker stack deploy requires that the docker-compose.yml file conform to at least version 3.0 syntax.
Installing “Docker-Compose”
On macOS, Windows, as well as recent installations on Linux, docker compose is an integralpart of Docker. You proceed as follows to check that yourself:
docker compose version
Docker Compose version 2.11.1
For older Linux installations, you should test to see if you can run docker compose without a hyphen. Only if it comes to the error message compose is not a docker command will a manual installation of the conventional command docker-compose be required. To do this, you need to run the following command, replacing 1.29.2 with the current version number:
sudo curl -L "https://github.com/docker/compose/releases/\
download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
docker-compose version 1.29.2
The installation command for the latest version of docker compose can be found on the following pages:
If the /usr/local/bin directory isn’t included in the PATH environment variable, you can either modify PATH accordingly (e.g., to .bashrc or .zshrc) or perform the installation directly in /usr/bin. To do this, you want to replace /usr/local/bin/docker-compose with /usr/bin/docker-compose twice in the preceding commands.
If you work with rootless Docker, you can simply install docker-compose into the local bin directory. This doesn’t require any root privileges.
YAML Ain’t Markup Language Syntax
Before you can run docker compose or docker stack deploy, you must create a file named docker-compose.yml. The extension *.yml denotes the YAML Ain’t Markup Language (YAML). We’ve briefly summarized the syntax rules of YAML for you here:
- --- introduces a new section.
- # starts a comment that extends to the end of the line.
- Strings can be expressed as "abc" or 'abc'. However, this is only mandatory in exceptional cases, for example, if the string contains special characters or can be interpreted as another YAML expression.
- Several expressions introduced with - form a list:
- red
- green
- blue
Alternatively, lists can be enclosed in square brackets:
[red, green, blue]
- Associative lists (key-value pairs) are created in the key: value format:
name: Howard Hollow
age: 37
Here, too, there’s a space-saving variant, but this time in curly brackets:
{name: Howard Hollow, age: 37}
- | introduces a text block in which the line breaks are preserved:
codeblock: |
Line 1
Line 2
- > introduces a text block in which line breaks are ignored, but empty lines are kept:
textblock: >
Text that
belongs together.
Here begins the
second paragraph.
All presented elements can be nested within each other. The structure is created by indentations. Note that spaces must be used here (no tabs!). When accessing the elements, the identifiers (keys) are strung together.
# sample.yaml file
data:
list:
- item1
- item2
key1: >
This text is assigned to the
'data.key1' key.
key2: |
code line 1
code line 2
Some advanced syntax elements of YAML, which usually don’t play a role in dockercompose. yml files, are documented in Wikipedia:
https://en.wikipedia.org/wiki/YAML
To read YAML files, you can use the Python script shyaml. On Ubuntu, you can install the command as follows:
sudo apt install python-pip
sudo pip install shyaml
shyaml get-value data.list < sample.yaml
- item1
- item2
When you experiment with YAML files, the YAML validators or parsers on the following websites are also quite useful:
Editor’s note: This post has been adapted from a section of the book Docker: Practical Guide for Developers and DevOps Teams by Bernd Öggl and Michael Kofler.
Comments