Comment avoir des images docker tout le temps à jour (FR)
jeu. 16 janvier 2020 Dan LousquiComment avoir des images docker tout le temps à jour
Docker, le nouvel AppStore des applications auto-hébergées
L'auto-hébergement, c'est la meilleure façon de détenir soi-même ses données, et de s'assurer d'avoir un service qui tourne en toute indépendance. Des alternatives pour les principaux services existent afin de tout avoir chez soi :
- Versionner son code privé sur un Gitlab, au lieu de d'héberger son code sur Github ;
- Héberger ses photos avec Nextcloud plutôt que d'avoir un abonnement sur Dropbox / iCloud / Google Drive / OneDrive ;
- Discuter sur comment changer le monde avec Mattermost, à la place d'utiliser Slack ;
- Tenir sa veille avec tt-rss, alors que Google Reader n'existe plus.
De plus, installer ces services n'a jamais été aussi simple avec docker
. En effet, si on regarde la procédure
d'installation pour ces services, cela tient généralement en deux lignes :
docker pull organisation/service:latest
docker run -d organisation/service
On voit donc que la fonction docker pull
est un très bon moyen pour faire son shopping d'applications que l'on
souhaite installer (j'assume ce raccourci, qui ne prend pas en compte l'exposition, la persistance des données, et plein
d'autres détails, dont certains font l'objet d'articles de ce blog).
Problématique des mises à jour
Contrairement aux gestionnaires de paquets / applications, docker
ne propose pas de notification de mise à
jour. Il n'est pas possible de vérifier si les versions des conteneurs lancés sont à jour.
D'ailleurs, dans l'outil de base, il n'existe aucune façon (simple) de le vérifier !
Prenons l'exemple (fictif) de organisation/service:latest
, au moment où l'on a effectué le docker pull
, le client
docker
ira sur le registre d'images (par défaut index.docker.io
), récupérera le manifest
pour
organisation/service
, et récupérera les binaires correspondants au tag latest
. Cependant, quelques temps plus tard,
le tag latest
ne correspondra pas forcément à la version téléchargée.
Pour mettre à jour, il suffit de ré-exécuter la commande docker pull
, et de recréer le conteneur. Par contre, il
n'existe aucun moyen de savoir à l'avance si cette commande est nécessaire ou pas.
Du coup, si on met un place un cron pour effectuer régulièrement un docker pull
, la mise à jour sera automatique, et
peut éventuellement générer des effets secondaires (par exemple, gitlab peut nécessiter de
lancer un script de changement de droit, tt-rss demande de temps en temps des migrations).
Mais comment faire ? (spoiler: avec docker-image-version-watcher)
Afin de pouvoir savoir si une image docker
est à jour, il faut comparer l'identifiant de l'image d'un conteneur avec
celui ayant le même tag sur le registre d'image.
On peut faire tout ça en python :
- Récupérer l'identifiant des images des conteneurs avec docker-py ;
- Récupérer l'identifiant des images avec le même tag avec python-dxf.
(Et si jamais l'image est construite localement, on peut faire la comparaison avec ce qu'il y a dans le champ FROM
du
Dockerfile
)
J'ai réalisé un script qui effectue toutes ces opérations, le code est disponible sur le dépôt git
TheBlusky/docker-image-version-watcher.
Et devinez quoi ? Ce script est auto-contenu dans une image docker
! L'installation est donc très simple :
docker pull theblusky/docker-image-version-watcher
docker run -it --rm \
-v /var/run/docker.sock:/var/run/docker.sock \ # Nécéssaire pour intérroger docker
theblusky/docker-image-version-watcher
Il est même possible (cf. le readme) d'envoyer des notifications gotify, slack ou mattermost lorsqu'une différence est trouvée. Par exemple, avec gotify
Aller plus loin
Il s'agit là d'un script fait rapidement, et qui suit très largement le principe de Pareto. Cela fait 80% de ce que j'en attends, pour pas beaucoup de travail (ça m'a pris moins de 30 minutes à développer).
On pourrait cependant aller bien plus loin en faisant, par exemple :
- Des mises à jours automatiques des conteneurs (assez simple à faire si on utilise
docker-compose
, mais comme expliqué précédemment, il faut de temps en temps effectuer des opérations de migrations manuelles) ; - Implémenter une interface graphique, permettant de mettre à jour via une interface web ;
- Être compatible avec les registres d'images privées ;
- Mettre en place des principes de récursivités pour vérifier que les images construites localement à partir d'image elle-même construite localement soit à jour.
Le code étant public, n'hésitez pas à faire vos propositions !