by Georg Ledermann

Updating Docker services with Portainer webhooks

Continuous Delivery

Photo by Matthew Dockery on Unsplash

Photo by Matthew Dockery on Unsplash

Some time ago I wrote about using Portainer for Docker hosting and using GitLab as container registry. Due to the further development of Portainer there is an interesting improvement regarding the installation of updates.

To update my Docker services I’ve been using Shepherd, a small tool that constantly polls the registry to see if a new Docker image is available and then fetches it from there, updating the running container with it. This works, but is not perfect: It leads to a basic load of the host and updates are delayed noticeably, especially if there are lots of services to check.

It would be better if a push mechanism could be used instead of polling, so that action is taken only when an updated image is available. Exactly this is possible with the recently released version 1.19.2 of Portainer: Now you can enable a webhook for each service. This webhook reacts to POST requests and performs an update.

This can easily be integrated into a CI/CD pipeline, I want to describe it using GitLab CI:

Step 1: Activate webhook in Portainer

First, the webhook for the desired service needs to be activated in Portainer. This generates an endpoint we will use later:

Portainer webhook
Enabling webhooks in Portainer

Step 2: Add CI variable in GitLab

Second, this endpoint must be made known to the CI/CD. In GitLab I’m adding a variable for this. Caution: If the same image is used for several services, several webhooks are required accordingly.

GitLab variables
Setting GitLab variables

Step 3: Enhance .gitlab-ci.yml

In the CI script .gitlab-ci.yml this variable needs to be used to post a request to the webhook after the image was successfully pushed to the Docker registry. The script will look like this:

1
2
3
4
5
6
7
release:
  script:
    - ...
    - docker build ...
    - docker push ...
    - curl -X POST $PORTAINER_HOOK_APP
    - curl -X POST $PORTAINER_HOOK_WORKER

That’s it. Now, after a new image is released, the Portainer host gets informed about this, so an update can be installed immediately.

BTW: I’m still using Shepherd, but for external images only, where an update check at longer intervals is sufficient, e.g. once a day.