What Is?

What Is Docker Compose?

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.




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



       - 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:




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.


Docker: Practical Guide for Developers and DevOps Teams
Docker: Practical Guide for Developers and DevOps Teams

Learn the ins and outs of containerization in Docker with this practical guide! Begin by installing and setting up the platform. Then master the basics: get to know important terminology, understand how to run containers, and set up port redirecting and communication. You’ll learn to create custom images, work with commands, and use key containerization tools. Gain essential skills by following exercises that cover common tasks from packaging new applications and modernizing existing applications to handling security and operations.

Learn More
Rheinwerk Computing
by Rheinwerk Computing

Rheinwerk Computing is an imprint of Rheinwerk Publishing and publishes books by leading experts in the fields of programming, administration, security, analytics, and more.