16

I found this question, but that one uses cron - I'd like to use a systemd service instead. My docker-compose.yml is in /home/me, and I run it with sudo docker compose up (and just keep it running in the background with tmux), and stop it with sudo docker compose down.

While functional, I'd rather do this using a systemd service to start/stop my docker-compose.yml file.

How can I turn my docker-compose.yml file into a (working) systemd service?

cocomac
  • 3,824

5 Answers5

18

I'll assume the docker-compose file is at /home/cocomac/docker-compose.yml, but you should replace it in my example with whatever the path to your docker compose file is.

First, let's create our service file. I like the text editor micro, personally, but feel free to use a different one. I'll call my service docker-compose.service, and it will be stored in /etc/systemd/system. Feel free to use a different name if you'd like, although if you do, remember to use that name when following the rest of this answer.

First, let's create and open the file with a text editor:

$ micro /etc/systemd/system/docker-compose.service

Put the following into the file:

[Unit]
Description=Some personal Docker containers
After=docker.service
Requires=docker.service

[Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/bash -c "docker compose -f /home/cocomac/docker-compose.yml up --detach" ExecStop=/bin/bash -c "docker compose -f /home/cocomac/docker-compose.yml stop"

[Install] WantedBy=multi-user.target

This gives our service a description, start + stop commands, as well as what it requires to be running before it starts. See this Arch Wiki page for an explanation of the different service types and what RemainAfterExit does.

Save the file and exit your text editor. You should now be able to do sudo systemctl start docker-compose to start your new systemd service. It may take a moment while it creates the containers, but once it finishes starting, you can do sudo systemctl status docker-compose to check the status of your service. You can also do sudo systemctl stop docker-compose to stop it (or sudo systemctl enable docker-compose to autostart it on boot)

cocomac
  • 3,824
4

Using the following for the Service stanza also works & has the benefit that you can view logs using journalctl -u docker-compose:

[Service]
Type=simple
ExecStart=/bin/bash -c "docker-compose -f /home/cocomac/docker-compose.yml up"
ExecStop=/bin/bash -c "docker-compose -f /home/cocomac/docker-compose.yml stop"

Note that the docker-compose command does not include the --detach flag and you do not need the RemainAfterExit option. Note also that on the version of Ubuntu I tested this on (20.04), docker-compose is a separate command.

monkeymind
  • 41
  • 1
2

If using systemd I prefer to use systemd to keep track of the service and take action if something happen to it. for that reason the run should be type=simple and not type=oneshot.

It is better to run docker instead sh or bash.

here is updated one

[Unit]
Description=Airflow
After=docker.service
Requires=docker.service

[Service] Type=simple Restart=always WorkingDirectory=/opt/airflow User=airflow Group=docker ExecStart=/usr/bin/docker compose --profile website up ExecStop=/usr/bin/docker compose --profile website stop

[Install] WantedBy=multi-user.target

Note that docker supports a policy to keep the containers up and running and it would be better to use that instead of systemd.

1

If you use restart: always in your docker compose file (which is fairly typical), then the docker daemon will automatically restart the container when the daemon itself starts up -- which means that you don't need to use systemd to have it automatically running all the time.

You will still need to re-run docker-compose if you make changes to the compose file or to pull updates; this will not occur automatically. But this does not require a systemd file.

Pablo Bianchi
  • 17,371
Miral
  • 111
1

You can also start systemd unit files listed in your user folder, and have them run on a regular basis. E.g. I have a certbot container that runs daily, to keep my ftp server's certificate up-to-date.

Based on the answer here.

Set your user profile to 'linger', with loginctl enable-linger ${USER}.

Create .service and .timer unit files in ~/.config/systemd/user. e.g.

~/.config/systemd/user/certbot-ftp.service

[Unit]
Description=Certbot LetsEncrypt renewal for vsftpd Server

[Service] Type=oneshot ExecStart=docker compose -f ~/docker-projects/ftp/compose.yaml restart certbot

[Install] WantedBy=default.target

~/.config/systemd/user/certbot-ftp.timer

[Unit]
Description=Run Certbot on a daily basis

[Timer] OnCalendar=daily Persistent=true

[Install] WantedBy=timers.target

Then, to enable the service and associated timer, which will happen whether or not you're logged in (because login lingering has been enabled):

systemctl --user enable certbot-ftp --now
Alex Leach
  • 111
  • 3