Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maj-stack-compose
Script shell qui parcourt toutes les stacks docker compose d'un répertoire racine, détecte celles dont au moins une image a une nouvelle version, et les relance proprement (down puis up -d).
Principe
Chaque sous-répertoire de la racine (par défaut /home) contenant un fichier compose est une stack :
/home
├── freshrss/ compose.yaml → stack « freshrss »
├── gitea/ docker-compose.yml → stack « gitea »
├── immich/ compose.yml → stack « immich »
└── notes/ (pas de fichier compose → ignoré)
Pour chaque stack, le script :
- vérifie le fichier compose avec
docker compose config -q:- fichier vide → stack ignorée sans rien afficher ;
- fichier invalide → erreur affichée en rouge ;
- ignore les stacks arrêtées (sauf avec
-a), pour ne pas démarrer ce qui a été coupé volontairement ; - télécharge les images avec
docker compose pull. Cette étape ne touche pas aux conteneurs qui tournent ; - compare, pour chaque conteneur, l'image qu'il utilise avec l'image qui vient d'être téléchargée pour le même tag ;
- si au moins une image a changé (ou avec
-f), relance toute la stack :docker compose downpuisdocker compose up -d.
Les fichiers compose reconnus sont, dans cet ordre : compose.yaml, compose.yml, docker-compose.yaml, docker-compose.yml.
Prérequis
- Linux avec Docker et Docker Compose v2 (commande
docker compose) ; flock(paquetutil-linux, présent sur toutes les distributions courantes) ;- un utilisateur ayant accès à Docker (root ou membre du groupe
docker).
Installation
git clone https://gitea.vlab.bzh/vLab-BZH/maj-stack-compose.git
cd maj-stack-compose
chmod +x update-stacks.sh
Utilisation
update-stacks.sh [-v | -q] [-n] [-f] [-p] [-a] [RACINE]
| Option | Effet |
|---|---|
-v |
verbose : détaille chaque conteneur (image actuelle → nouvelle), chaque commande docker et sa sortie |
-q |
quiet : une seule ligne par stack (nom, répertoire, état) |
-n |
dry-run : détecte les mises à jour mais ne relance rien |
-f |
force : down + up -d de chaque stack, même sans mise à jour |
-p |
prune : supprime les images orphelines à la fin (docker image prune -f) |
-a |
all : traite aussi les stacks arrêtées (sinon elles sont ignorées) |
-h |
affiche l'aide |
RACINE |
répertoire contenant les stacks (défaut : /home) |
Exemples
Voir ce qui serait mis à jour, sans rien toucher :
./update-stacks.sh -n /home
Mettre à jour, avec un affichage minimal :
./update-stacks.sh -q /home
Mettre à jour, puis supprimer les anciennes images :
./update-stacks.sh -p /home
Relancer toutes les stacks, y compris celles qui sont arrêtées :
./update-stacks.sh -f -a /home
Affichage
Couleurs
| Couleur | Signification |
|---|---|
| 🟢 vert | stack à jour |
| 🟡 jaune | mise à jour détectée, appliquée (ou à faire en dry-run), ou redémarrage forcé |
| 🔴 rouge | erreur (fichier compose invalide, échec du pull, du down ou du up -d) |
| gris | stack arrêtée, ignorée |
Les couleurs sont désactivées automatiquement quand la sortie n'est pas un terminal (cron, redirection vers un fichier), ou si la variable NO_COLOR est définie.
Mode quiet (-q)
arcane /home/arcane ✔ à jour
arcane-agent /home/arcane-agent arrêtée
freshrss /home/freshrss ✔ à jour
immich /home/immich ↑ mise à jour appliquée
broken /home/broken ✘ erreur (fichier compose invalide)
yaml: line 3: mapping values are not allowed
Mode normal (par défaut)
[2026-10-02 04:00:01] Racine : /home
[2026-10-02 04:00:01] == Stack : immich (/home/immich/compose.yml)
[2026-10-02 04:00:09] ↑ immich-server (ghcr.io/immich-app/immich-server:release) : nouvelle image disponible
[2026-10-02 04:00:31] ✔ stack relancée (down + up -d) : mise à jour
[2026-10-02 04:00:31] Terminé. Stacks relancées : 1 immich | Échecs : 0
Mode verbose (-v)
Ajoute l'état de chaque conteneur avec les identifiants courts des images, ainsi que chaque commande docker ($ docker compose pull …) suivie de sa sortie complète.
En mode normal et quiet, la sortie de docker est masquée ; elle n'est affichée, sous la stack concernée, qu'en cas d'échec.
Automatisation (cron)
Exemple : chaque nuit à 4 h, avec nettoyage des images et journal dans /var/log (crontab de root) :
0 4 * * * /opt/maj-stack-compose/update-stacks.sh -p /home >> /var/log/update-stacks.log 2>&1
Un verrou (/tmp/update-stacks.lock) empêche deux exécutions simultanées.
Code de retour
| Code | Signification |
|---|---|
0 |
toutes les stacks ont été traitées sans erreur |
1 |
au moins une stack en erreur, une autre exécution en cours, Docker Compose v2 absent ou racine introuvable |
Limites
- Tags figés : seules les nouvelles images publiées sous le même tag sont détectées (
latest,release,16…). Une image figée surnginx:1.25.3ne passera jamais en1.25.4: changer de version reste une décision manuelle. - Images construites localement : les services avec
build:sont ignorés aupull(--ignore-buildable) ; ils ne déclenchent donc pas de mise à jour. - Coupure de service :
downpuisup -darrête toute la stack quelques secondes, y compris les conteneurs dont l'image n'a pas changé. - Profondeur : seuls les sous-répertoires directs de la racine sont examinés.
Documentation
docs/architecture.png: schéma de fonctionnement du script ;docs/architecture.excalidraw: source du schéma, modifiable sur excalidraw.com (menu Ouvrir).
