Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Run multiple Docker Compose services on Debian/Ubuntu

profile picture
Author
Bernd Stellwag
Published
2019-03-11
Time to read
4 minutes reading time

Introduction

This tutorial will show you how you can run multiple Docker Compose services via a systemd service template.

Prerequisites

Step 1 - Create Docker Compose files

For this tutorial we will store our Docker Compose service configurations under /etc/docker-compose.

mkdir /etc/docker-compose

Just as an example, let's say we want to run watchtower to keep our running containers up to date. We have to create a directory for that service in /etc/docker-compose:

mkdir /etc/docker-compose/watchtower

And we need the according Docker Compose file at /etc/docker-compose/watchtower/docker-compose.yml:

version: "3"

services:
  watchtower:
    image: containrrr/watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: --cleanup --no-pull

For more info about the options specified under command take a look at watchtower. Here we specify that old images should be removed after updating to a new image (--cleanup). We also tell watchtower that it should not check for newer images itself (--no-pull). This option is recommended if you are building your own images (without pushing them to the Docker Registry). We will take care of pulling new images regularly later. If you don't plan on building your own images then you can just omit --no-pull and also skip step 3.

Step 2 - Create the systemd service template

Now we create the systemd service template at /etc/systemd/system/docker-compose@.service:

[Unit]
Description=docker-compose %i service
Requires=docker.service network-online.target
After=docker.service network-online.target

[Service]
WorkingDirectory=/etc/docker-compose/%i
Type=simple
TimeoutStartSec=15min
Restart=always

ExecStartPre=/usr/local/bin/docker-compose pull --quiet --ignore-pull-failures
ExecStartPre=/usr/local/bin/docker-compose build --pull

ExecStart=/usr/local/bin/docker-compose up --remove-orphans

ExecStop=/usr/local/bin/docker-compose down --remove-orphans

ExecReload=/usr/local/bin/docker-compose pull --quiet --ignore-pull-failures
ExecReload=/usr/local/bin/docker-compose build --pull

[Install]
WantedBy=multi-user.target

This service template will:

  • Try to pull new versions of the used Docker images on startup and reload of the systemd service
  • Try to build the images if it's configured this way in the docker-compose.yml on startup and reload of the systemd service
  • Remove orphan containers (e.g. after you changed a containers name or removed a container from the docker-compose.yml)

If you wonder why the start timeout is a bit long, some Docker images may need some time to be built which is done when starting the service.

Now we make systemd reload the service files so we can actually use it:

systemctl daemon-reload

Step 3 - Regularly pull and build new Docker images (Optional)

Since we configured the service template to pull and build our images on a reload of the systemd service we can also create a cronjob for that so we can benefit from regularly pulled/built images:

echo '0  4    * * *   root    /bin/systemctl reload docker-compose@*.service' >> /etc/crontab

Please note that this only works as intended in combination with watchtower as shown above in step 1 as new images will not automatically be used. When the systemd service is reloaded Docker Compose will pull and build new images. Watchtower will then automatically pick up those new images and restart the according containers with the new images.

Step 4 - Start Docker services

With this setup we can now start a Docker Compose service (in this case 'watchtower'):

systemctl start docker-compose@watchtower

And enable it to start on boot:

systemctl enable docker-compose@watchtower

Conclusion

You have now set up an environment where you can easily start different Docker Compose services as systemd services. For each additional service you just need to:

  • Create the according /etc/docker-compose/servicename directory
  • Create at least a /etc/docker-compose/servicename/docker-compose.yml file (and whatever else you need for the service)
  • Start the service via systemctl start docker-compose@servicename
  • (Optional) Start the service on boot with systemctl enable docker-compose@servicename
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue

Discover our

Dedicated Servers

Configure your dream server. Top performance with an excellent connection at an unbeatable price!

Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more