Sommaire

Avoir ces images Docker à jour avec DIUN

Problème

Comme souvent dans récents articles, ces derniers sont issue d’un problème que j’ai et que je cherche à résoudre. Celui-ci en fait aussi partie !

J’essaye de rester au maximum à jour dans les versions des logiciels que j’utilise.
Pour les packages, j’utilise mon script pour être notifié de la disponibilité de MAJ pour que je les applique (ceux de sécurités sont eux automatiquement installés).
Pour les images Docker que j’utilise, mes choix ne couvrent pas tous les cas :

  • Abonné au projet GitHub, je suis notifié de nouvelles releases (quand le projet est sur GitHub)
  • Plugin Nagios check_docker non maintenu (ne fonctionne qu’avec le registry hub.docker.com)

Ne trouvant pas de solution applicable à tous les cas, j’avais un peu abandonné l’idée de résoudre ce problème…
Cependant, j’ai trouvé une solution et c’est ce que je souhaite vous partager ici.

Solution

J’ai récemment découvert DIUN (Docker Image Update Notifier) qui permet d’envoyer une notification lorsqu’une MAJ d’une image Docker que j’utilise est disponible !
Cerise sur le gâteau, il est nativement compatible avec Gotify (mon article sur le sujet) !

Cet outil fait exactement ce que je souhaite : être notifié d’une MAJ d’une image Docker que j’utilise en respectant le tag que j’utilise.
Et le développeur est un Français !

Nous allons donc voir ici comment le mettre en place en utilisant Gotify pour les notifications.

Configuration

Aperçu

Afin de comprendre ma façon de configurer DIUN, le mieux et je vous montre mon docker-compose.yml :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
version: "3.8"

services:
  diun:
    image: crazymax/diun:latest
    container_name: diun-app
    restart: unless-stopped
    command: serve
    environment:
      - TZ=${MY_TZ}
      - LOG_LEVEL=${MY_LOG_LEVEL}
      - LOG_JSON=${MY_LOG_JSON}
      - DIUN_WATCH_WORKERS=${MY_DIUN_WATCH_WORKERS}
      - DIUN_WATCH_SCHEDULE=${MY_DIUN_WATCH_SCHEDULE}
      - DIUN_PROVIDERS_DOCKER=${MY_DIUN_PROVIDERS_DOCKER}
      - DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT=${MY_DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT}
      - DIUN_NOTIF_GOTIFY_ENDPOINT=${MY_DIUN_NOTIF_GOTIFY_ENDPOINT}
      # - DIUN_NOTIF_GOTIFY_TOKEN=${MY_DIUN_NOTIF_GOTIFY_TOKEN}
      - DIUN_NOTIF_GOTIFY_TOKENFILE=${MY_DIUN_NOTIF_GOTIFY_TOKENFILE}
      - DIUN_NOTIF_GOTIFY_PRIORITY=${MY_DIUN_NOTIF_GOTIFY_PRIORITY}
      - DIUN_NOTIF_GOTIFY_TEMPLATETITLE=${MY_DIUN_NOTIF_GOTIFY_TEMPLATETITLE}
      - DIUN_NOTIF_GOTIFY_TEMPLATEBODY=${MY_DIUN_NOTIF_GOTIFY_TEMPLATEBODY}
    volumes:
      - /etc/gotify.token:/etc/gotify.token:ro
      - /var/lib/diun/data/:/data/
      - /var/run/docker.sock:/var/run/docker.sock

Afin de pouvoir revenir sur ma configuration plus tard sans avoir à fouiller dans plein de fichiers pour le comprendre, j’ai choisi d’effectuer la configuration via les variables d’environnement.
On peut aussi le faire via un fichier de configuration, mais je préfère la méthode des variables d’environnement car plus universelle.

Variables d’environnements

Comme on peut le voir, les variables d’environnements sont associées à des variables que j’ai définies selon le modèle suivant :

VARIABLE = $MA_VARIABLE

Avec une définition du type :

MA_VARIABLE=“la valeur que je lui affecte”

Cela me permet d’introduire une fonctionnalité que j’utilise maintenant sur mes Docker Compose : l’utilisation de fichier de variable d’environnement.
En effet, si on a un fichier .env dans le même dossier que notre docker-compose.yml, se dernier est chargé avant le Docker Compose. Cela permet donc d’associer aisément des valeurs aux variables configurables de l’application.

Pas comme les autres...

La plupart des exemples d’utilisation qui utilisent la même méthode que moi ne font pas la différence entre la variable de l’éditeur et la leur.

Vous trouverez donc des exemples de type :

VARIABLE = $VARIABLE

Cela fonctionne, mais je ne le trouve pas assez clair pour moi.

Voici donc mon fichier .env :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
MY_TZ=Europe/Paris
MY_LOG_LEVEL=info
MY_LOG_JSON=false
MY_DIUN_WATCH_WORKERS=20
MY_DIUN_WATCH_SCHEDULE=0 */6 * * *
MY_DIUN_PROVIDERS_DOCKER=true
MY_DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT=true
MY_DIUN_NOTIF_GOTIFY_ENDPOINT=https://gotify.example.com
MY_DIUN_NOTIF_GOTIFY_TOKEN=AZERTY
MY_DIUN_NOTIF_GOTIFY_TOKENFILE=/etc/gotify.token
MY_DIUN_NOTIF_GOTIFY_PRIORITY=5
MY_DIUN_NOTIF_GOTIFY_TEMPLATETITLE={{ .Entry.Image }} {{ if (eq .Entry.Status "new") }}is available{{ else }}has been updated{{ end }}
MY_DIUN_NOTIF_GOTIFY_TEMPLATEBODY=Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }} {{ if (eq .Entry.Status "new") }}is available{{ else }}has been updated{{ end }} on {{ .Entry.Image.Domain }} registry.

Pour d’autres options de configuration, je vous invite à consulter la documentation officiel sur ce sujet.

Astuce
Dans un Docker Compose où sont définis plusieurs services, je mets l’intégralité de leurs variables dans mon seul fichier .env.
Cela rend encore plus simple la relecture de la configuration.

Paramètres

DIUN

Sans configuration particulière, DIUN consultera exclusivement les images dont les conteneurs sont lancés avec le label diun.enable à true.

En Docker Compose :

1
2
    labels:
      - "diun.enable=true"

Moi, je souhaite suivre les images de tous les conteneurs que j’utilise. De ce fait, je met la variable DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT à true.
De cette manière, cela me permet de ne pas a avoir à éditer tout mes Docker Compose.

D’où la partie correspondante de mon fichier .env :

1
MY_DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT=true

Gotify

1
2
3
4
5
6
7
MY_DIUN_NOTIF_GOTIFY_ENDPOINT=https://gotify.example.com
MY_DIUN_NOTIF_GOTIFY_TOKEN=AZERTY
MY_DIUN_NOTIF_GOTIFY_TOKENFILE=/etc/gotify.token

MY_DIUN_NOTIF_GOTIFY_PRIORITY=5
MY_DIUN_NOTIF_GOTIFY_TEMPLATETITLE={{ .Entry.Image }} {{ if (eq .Entry.Status "new") }}is available{{ else }}has been updated{{ end }}
MY_DIUN_NOTIF_GOTIFY_TEMPLATEBODY=Docker tag {{ if .Entry.Image.HubLink }}[**{{ .Entry.Image }}**]({{ .Entry.Image.HubLink }}){{ else }}**{{ .Entry.Image }}**{{ end }} {{ if (eq .Entry.Status "new") }}is available{{ else }}has been updated{{ end }} on {{ .Entry.Image.Domain }} registry.

En consultant mes variables, on voit que je ne précise pas le token directement, mais plutôt un lien vers un fichier.

Attention !

Le fichier contenant le token ne doit pas avoir de saut de ligne !

Je l’ai donc créer de la manière suivante :

1
echo -n "AZERTY" > /etc/gotify.token

Test

Une fois le Docker Compose de lancé (docker compose up -d), on peut accéder à la CLI avec un

1
docker exec -it diun-app sh

On peut donc utiliser les commandes diun et lancer une commande de notification de test.

1
2
diun --help
diun notif test
/docker-images-update-diun/img/Screenshot_1.webp
Notification de test

Résultat

Le paramétrage de planification par défaut 0 */6 * * * a pour effet de lancer la commande aux heures suivantes : 00h00, 06h00, 12h00, 18h00.

Après quelques jours (le temps d’avoir les MAJs de mes applis), je commence à recevoir des notifications :

/docker-images-update-diun/img/Screenshot_2.webp
Mise à jour de disponible

Je n’ai donc plus qu’à lancer mon script pour mettre à jour mes conteneurs !