Ich stand vor der Herausforderung, dass ich wissen wollte, ob es für Docker-Images, die ich verwende, Updates bzw. eine neue Image-Version gibt. Der Klassiker ist latest wie z.B. bei jellyfin/jellyfin:latest. Aber auch Haupt-Versionen werden zum Teil benannt: postgres:13 .

Bei der Verwendung von docker compose sind die Docker-Images sind z.B. in einer docker-compose.yml-Datei hinterlegt, wo ich das selbstgeschrieben Script update_docker_images.sh verwende, um die Container zu aktualisieren.

Mit dem Tool watchtower bin ich nicht zurecht gekommen bzw. es hat meine Anforderungen nicht erfüllt oder ich sie nicht umsetzen konnte. Eine Hürde war, dass ein Teil der Server, die ich betreue, keinen Zugriff auf das Internet haben. Ebenso baue ich durchaus eigene Images und Watchtower “sieht” meines Wissens nicht das Dockerfile was im Build-Prozess benötigt wird. Updates des verwendeten Basis-Images bekomme ich also nicht mit.

Somit musste eine eigene Lösung her. Zeitgleich hatte ich das Tool jq entdeckt und sah es als Möglichkeit, mich an einem konkreten Beispiel mit diesem auseinanderzusetzen.

Konfigurationsdatei

Damit ich mir (bzw. das Script) merken kann, wann der letzte pull eines Docker-Images stattfand, brauche ich eine Konfigurationsdatei.

Der Aufbau der Konfigurationsdatei ist eine Datei im json-Format. Jeder Unterelement hat genau einen Wert.

Es gibt folgende Elemente

  • imagename
  • tag
  • info
  • date

Diese werden im Folgenden erläutert.

imagename

Zum Herunterladen sollen zwei Docker-Images als Beispiel dienen

1docker pull jellyfin/jellyfin:latest
2docker pull postgres:13

Der einfache Fall ist die Angabe des Names des Docker-Images, also:

1"imagename": "jellyfin/jellyfin"

Alle Docker-Images, die das Badge Docker Official Image haben, muss noch ein library davor gestellt bekommen. Das ist später für das Script wichtig.

1"imagename": "library/postgres"

tag

Aus dem obigen docker pull Befehl kann jetzt hier der Tag angeben werden. Durch die Trennung vom Image-Namen und Tag, lassen sich auch unterschiedliche Versionen beobachten.

info

Dies ist reines Prosa-Feld und dient zur eigenen Information bzw. Dokumentation. Ich schreibe hier z.B. die URL zum Changelog auf.

Ein anderer Einsatzzweck ist die Dokumentation, in welchem docker-compose-File ich das Image verwendet. In unten genannten Fall, z.B. im Dunstkreis von paperless-ngx .

date

Hier steht der Zeitstempel drin, wann das jeweilige Image zuletzt auf docker-Hub hochgeladen wurde. Die Information stammt aus der json-Antwort vom Docker-Hub; dort steht es im Element last_updated und genau dieser Wert wird mit dem Wert der Konfigurations-Datei verglichen.

Komplette Beispieldatei

 1[
 2  {
 3    "imagename": "library/postgres",
 4    "tag": "13",
 5    "info": "paperless-ngx",
 6    "date": "2023-11-03T05:09:17.243391Z"
 7  },
 8  {
 9    "imagename": "library/redis",
10    "tag": "7.0",
11    "info": "paperless-ngx",
12    "date": "2023-11-04T04:12:52.019118Z"
13  },
14  
15  {
16    "imagename": "jellyfin/jellyfin",
17    "tag": "latest",
18    "info": "",
19    "date": "2023-11-05T18:28:02.143505Z"
20  }
21]

Das Script

Voraussetzungen

Das Script benötigte folgende installierte Tools

  • jq
  • curl
  • bash

Die Konfigurationsdatei muss im selben Verzeichnis sein, wie das Script.

Script-Aufruf

Das Script kann ohne Parameter aufgerufen werden. Es arbeitet die Konfigurationsdatei ab und sucht sich alle Elemente des Typs imagename heraus.

In einer while-Schleife pickt es sich dann das zugehörige Tag und den letzten Zeitstempel heraus.

Diese Angaben werden zu einer URL zusammengesetzt und das Ergebnis ausgewertet. Der Datenstrom besteht aus einer json-Antwort, wo wiederum ein Zeitstempel last_updated aufgeführt ist. Dieser Zeitstempel wird auf Docker-Hub aktualisiert, wenn von der Image-Maintainer*in ein neues Image hochgeladen (gepushed) wurde. Der Zeitstempel wird mit einem simplen String-Vergleich mit der Datumsangabe aus der Konfigurationsdatei verglichen. Sind beide gleich, wird eine “OK”-Meldung herausgegeben und das nächste Image wird abgearbeitet. Unterscheiden sich die Zeitstempel, wird eine Warnmeldung herausgegeben. Zusätzlich wird der Return-Codes des Scriptes auf 1 gesetzt, um diesen potentiell später auswerten zu können.

In beiden Fällen, wird der Inhalt der Elements info ausgeben. Dies ist z.B. im Rahmen eines Cronjobs hilfreich. Hier trage ich z.B. eine URL zu den Release-Infos ein, um mich über Änderungen vor einem Update zu informieren oder bekomme einen Hinweis, in welchen docker-compose-Dateien das Image verwendet wird.

Parameter “-q”

Der Parameter -q reduziert die Ausgabe des Scriptes. Images, die aktuell sind und wo es kein neues auf Docker-Hub gibt, werden nicht mehr ausgegeben. Das ist für cronjobs praktisch, weil ich da nur eine E-Mail bekommen möchte, wenn es neue Images gibt. Das reduziert das Mail-Aufkommen.

Parameter “-u”

Der Parameter -u erzeugt noch eine weitere Ausgabe am Ende des Scriptes.

WARNING: Neues Docker-Image verfuegbar library/postgres:13 seit 2023-11-23 13:08 ("2023-11-23T12:08:41.624052Z") Info: paperless-ngx
./update_rc.sh library/postgres:13 2023-11-23T12:08:41.624052Z # paperless-ngx

Um sich das händische Aktualisieren des neuen Zeitstempels zu erleichtern, gibt es das Script update_rc.sh. Die benötigten Parameter mit dem jeweiligen Zeitstempel werden benutzungsfertig für Copy und Paste auf STDOUT mit ausgeben.

Beispiel-Ausgabe

$ ./check_last_docker_pull.sh -u
WARNING: Neues Docker-Image verfuegbar jellyfin/jellyfin:latest seit 2023-11-29 22:57 ("2023-11-29T21:57:57.203009Z") Info: 
WARNING: Neues Docker-Image verfuegbar library/postgres:13 seit 2023-12-16 04:10 ("2023-12-16T03:10:26.057478Z") Info: paperless-ngx
WARNING: Neues Docker-Image verfuegbar library/redis:7.0 seit 2023-12-16 03:08 ("2023-12-16T02:08:55.087065Z") Info: paperless-ngx
./update_rc.sh jellyfin/jellyfin:latest 2023-11-29T21:57:57.203009Z # Info:  
./update_rc.sh library/postgres:13 2023-12-16T03:10:26.057478Z # Info: paperless-ngx 
./update_rc.sh library/redis:7.0 2023-12-16T02:08:55.087065Z # Info: paperless-ngx

Sofern das Image dann auf dem entsprechenden Computer oder Server heruntergeladen wurde, kann die Konfigurationsdatei mit dem oben ausgegeben Kommando aktualisiert werden; also z.B.

1./update_rc.sh library/redis:7.0 2023-12-16T02:08:55.087065Z

Der # ist gleichzeitig Kommentar in der Shell, so dass es nicht stört, wenn aus Versehen zu viel markiert wird.

check_last_github_release.sh

Allerdings gibt es inzwischen einige Images oder Tools, die auf github liegen bzw. in deren Docker-Registry. Da github ebenfalls eine API anbietet, dessen Ausgabe in einem ähnlichen JSON-Format anbietet, habe ich das obige Script etwas umgeschrieben.

Hier wird eine weitere Konfigurationsdatei benötigt mit dem Namen check_last_github_release.rc.json.

Folgende Elemente werden verwendet

  • repro
  • release
  • info

repro

Hier wird nach der selben Mimik wie weiter oben der Image-Name eingetragen.

1    "repro": "paperless-ngx/paperless-ngx",

release

Im Gegensatz zu oben verwende ich feste Versionsnummern:

1    "release": "1.17.4",

info

Hier gilt selbiges wie oben; eine kleine Stelle zur Dokumentation oder Verweis auf eine URL.

check_last_github_release.rc.json

Hier jetzt ein vollständiges Beispiel einer Konfigurationsdatei.

 1[
 2  {
 3    "repro": "paperless-ngx/paperless-ngx",
 4    "release": "1.17.4",
 5    "info": ""
 6  },
 7  {
 8    "repro": "mar10/wsgidav",
 9    "release": "4.3.0",
10    "info": ""
11  },
12  {
13    "repro": "restic/restic",
14    "release": "0.16.2",
15    "info": "https://restic.net/blog/"
16  },
17  {
18    "repro": "go-gitea/gitea",
19    "release": "1.20.5",
20    "info": "https://blog.gitea.com/"
21  }
22]

Das Script

Voraussetzungen

Ähnlich wie oben das Script check_last_docker_pull.sh benötigt es dieselben Software-Tools:

  • jq
  • curl
  • bash

Derzeit wird zum Auswerten zusätzlich noch

  • perl

benötigt. Dies soll zukünftig durch sed ersetzt werden, was IMHO verbreiteter installiert ist.

Script-Aufruf

Das Script selbst kann ohne Parameter aufgerufen werden. Ähnlich wie check_last_docker_pull.sh hangelt es sich durch die Konfigurationsdatei und prüft alle Repositorys auf neuere Versionen. Da in der URL mit dem Keyword latest gearbeitet werden kann, muss nur ein String-Vergleich mit der Versionsnummer aus der Konfigurationsdatei stattfinden. Bei Differenzen gibt es eine entsprechende Warnung. Die neue Version steckt schon in der json-Antwort und wird ebenfalls mit ausgegeben. Der Exit-Code ist auch hier wiederum 1.

Aktuell muss die neue Version nach einem erfolgten Update noch per Hand neu gesetzt werden. Perspektivisch soll es hier auch ein Update-Script geben, da ja alle Informationen vorliegen.

Parameter “-q”

Auch hier kann das Script mit dem Parameter -q aufgerufen werden, um den Output des Scriptes zu reduzieren.

Beispiel-Ausgabe

$ ./check_last_github_release.sh 
WARNING: Neues Release verfuegbar go-gitea/gitea alt: 1.20.5 neue Version 1.21.2 Info: https://blog.gitea.com/
OK: Release mar10/wsgidav Info: 
WARNING: Neues Release verfuegbar paperless-ngx/paperless-ngx alt: 1.17.4 neue Version 2.1.3 Info: 
OK: Release restic/restic Info: https://restic.net/blog/

Baustellen

Die oben erwähnten Baustellen sollen demnächst(tm) mal behoben werden. Wenn dem so ist, werde ich den Blog-Artikel aktualisieren und entsprechend kennzeichnen.

Die Scripte - der Code

Alle Scripte liegen auf GitLab innerhalb des Projektes cli-tools unterhalb des Verzeichnisses watch_docker_images , wo ich mehrere solcher Tools sammle