Skip to content

Instantly share code, notes, and snippets.

@Luzifer
Last active November 18, 2023 17:22
Show Gist options
  • Save Luzifer/7c54c8b0b61da450d10258f0abd3c917 to your computer and use it in GitHub Desktop.
Save Luzifer/7c54c8b0b61da450d10258f0abd3c917 to your computer and use it in GitHub Desktop.
Running docker-compose as a systemd service

Running docker-compose as a systemd service

Files

File Purpose
/etc/compose/docker-compose.yml Compose file describing what to deploy
/etc/systemd/system/docker-compose-reload.service Executing unit to trigger reload on docker-compose.service
/etc/systemd/system/docker-compose-reload.timer Timer unit to plan the reloads
/etc/systemd/system/docker-compose.service Service unit to start and manage docker compose

Installation

Put the above mentioned files in the corresponding places and let systemd load them:

# systemctl daemon-reload
# systemctl enable --now docker-compose.service docker-compose-reload.timer

Ansible role

The method shown here is also available as an Ansible role here: luzifer-ansible/docker-compose

[Unit]
Description=Refresh images and update containers
[Service]
Type=oneshot
ExecStart=/bin/systemctl reload-or-restart docker-compose.service
[Unit]
Description=Refresh images and update containers
Requires=docker-compose.service
After=docker-compose.service
[Timer]
OnCalendar=*:0/15
[Install]
WantedBy=timers.target
[Unit]
Description=Docker Compose container starter
After=docker.service network-online.target
Requires=docker.service network-online.target
[Service]
WorkingDirectory=/etc/compose
Type=oneshot
RemainAfterExit=yes
ExecStartPre=-/usr/local/bin/docker-compose pull --quiet
ExecStart=/usr/local/bin/docker-compose up -d
ExecStop=/usr/local/bin/docker-compose down
ExecReload=/usr/local/bin/docker-compose pull --quiet
ExecReload=/usr/local/bin/docker-compose up -d
[Install]
WantedBy=multi-user.target
@Luzifer
Copy link
Author

Luzifer commented Aug 16, 2018

@Ricordel you're right, this leads to broken deployments in case for example the registry is not available (had exactly that case this morning). I've made two changes to this Gist and also to the Ansible role:

  • Used reload-or-restart as you suggested
  • Made the docker-compose pull call non-mandantory

That way the start will not fail over the pull (it might start slightly older images but hey, better not the recent image than no container, right?) and ensure the service is started…

@pomazanbohdan
Copy link

pomazanbohdan commented Mar 9, 2019

Please raise the contents of docker-compose.service above the other two

image

or

image

@GoSpursGoNL
Copy link

Thank you. The first time I ran the last command, to start the services, I got this error:
sudo systemctl start docker-compose docker-compose-reload
docker-compose.service is not active, cannot reload.
Job for docker-compose-reload.service failed because the control process exited with error code.
See "systemctl status docker-compose-reload.service" and "journalctl -xe" for details.

Then I found out that docker-compose perfectly started. Then again I ran just the reload-service
sudo systemctl start docker-compose-reload

And it runs perfectly.

@Luzifer
Copy link
Author

Luzifer commented Nov 3, 2019

@GoSpursGoNL I've updated the README above. This should work better as the previous version started the docker-compose-reload.service instead as intended the docker-compose-reload.timer.

@GoSpursGoNL
Copy link

Thanks, looks good. Will the timer also pull image updates (so update software to newer versions)? I prefer to do that manually since some applcations that I use can be unstable until they provide a bugfix release. Should I disable the timer?

@Luzifer
Copy link
Author

Luzifer commented Nov 3, 2019

If you don't want automated updates you can either pin the specific image (image: alpine:3.9), then only that specific tag will be used (that's the way I'm using for unstable software) or you can disable the timer which does not fully save you from updates as docker-compose itself has update-checks built in and even though local versions are preferred there might be updates.

The most safe way to guarantee nothing changes is to use sha-pinning:
image: sha256:965ea09ff2ebd2b9eeec88cd822ce156f6674c7e99be082c7efac3c62f3ff652

(Though the last method is possible I wouldn't use it as then even security updates for the tag are no longer possible.)

@leeramsay
Copy link

I think I found a typo, ExecStartPre=-/usr/local/bin/docker-compose pull --quiet
should be this ExecStartPre=/usr/local/bin/docker-compose pull --quiet
shouldn't it?

@Luzifer
Copy link
Author

Luzifer commented Jul 25, 2020

@leeramsay Nah that's intentional. The - in front of the command tells systemd not to panic if the command exits non-zero (see systemd.service(5))… If an image cannot be pulled because of some registry had trouble that's okay at that point. The image will be updated later if it's already present on the machine. If not the next step will then cause an error…

@leeramsay
Copy link

Okie doke, thanks for the info!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment