Table of Contents
- Mise à jour des applications
- Principe général
- Exemple : mettre à jour Bonsai Webapp
- Mettre à jour une version précise (tag de release)
- Notes sur le workflow de release (CI)
- Revenir à une version précédente (rollback)
- Rollback Bonsai Webapp
- Rollback Bonsai API (avec ou sans restauration BDD)
- Ce que fait le workflow en coulisse
- Backups de la base de données
- Luz — déploiement par script (SSH direct, sans registre)
- Rollback Olhar (API + PWA, avec ou sans restauration BDD)
- Mettre à jour tous les services d'un coup
- Vérifications après mise à jour
Mise à jour des applications
Chaque application est packagée sous forme d'image Docker publiée sur le registre Gitea (git.goutailler-olivier.com) par la CI lors d'une release. La mise à jour en production consiste à récupérer la nouvelle image et à recréer le conteneur.
Principe général
cd <dossier-du-service>/
docker compose pull # télécharge la nouvelle image
docker compose up -d # recrée le conteneur si l'image a changé
docker compose up -d détecte automatiquement que l'image locale est différente de celle utilisée par le conteneur en cours et le recrée. Le temps d'indisponibilité est limité à la durée du redémarrage du conteneur (quelques secondes).
Exemple : mettre à jour Bonsai Webapp
Une nouvelle release a été publiée sur Gitea et l'image bonsai-webapp:latest a été mise à jour par la CI.
cd bonsai-webapp/
docker compose pull
docker compose up -d
Vérifier que le conteneur tourne bien avec la nouvelle image :
docker inspect bonsai-webapp --format '{{.Image}}'
# ou
docker compose ps
Mettre à jour une version précise (tag de release)
Par défaut les docker-compose.yml pointent sur :latest. Pour épingler une version spécifique, éditer le fichier et remplacer le tag :
image: git.goutailler-olivier.com/bonsai/bonsai-webapp:v1.2.3
Puis appliquer :
docker compose pull
docker compose up -d
Notes sur le workflow de release (CI)
fetch-depth: 0 requis sur le checkout
Le job release.yml de Bonsai-webapp (et Bonsai-api) effectue un git merge du tag de release dans main à la fin du pipeline. actions/checkout@v4 fait par défaut un clone superficiel (--depth 1), ce qui empêche git de trouver l'ancêtre commun entre le tag et main → erreur refusing to merge unrelated histories.
Solution appliquée : ajouter fetch-depth: 0 sur le step Checkout :
- name: Checkout
uses: https://github.com/actions/checkout@v4
with:
fetch-depth: 0
Sans ce paramètre, tout nouveau runner qui clone le dépôt avec historique limité fera échouer l'étape « Merge release to main ».
Bump de version commité avant le merge
Le step « Bump version in package.json » modifie package.json pour y inscrire la version de la release. Ce changement est commité sur le HEAD détaché (tag checkout) avant que le build Docker ne commence. Le step « Merge release to main » sauvegarde ensuite le hash de ce commit (RELEASE_HEAD) et merge ce commit (et non le tag) sur main :
- name: Bump version in package.json
run: |
# ... sed + git config ...
git add package.json
git commit -m "chore: set version to $VERSION"
- name: Merge release to main
run: |
RELEASE_HEAD=$(git rev-parse HEAD)
git checkout main
git merge --no-ff "$RELEASE_HEAD" -m "chore: release ..."
git push origin main
Pourquoi : sans ce commit préalable, git checkout main échoue avec "Your local changes would be overwritten by checkout" car package.json est modifié mais non commité.
Revenir à une version précédente (rollback)
Un workflow Gitea Actions dédié permet de déclencher un rollback sans toucher au serveur manuellement.
Rollback Bonsai Webapp
- Aller dans Gitea → Bonsai-webapp → Actions → Rollback → Run workflow
- Saisir la version cible (ex.
v1.2.3) - Lancer — Watchtower redéploie automatiquement
Rollback Bonsai API (avec ou sans restauration BDD)
- Aller dans Gitea → Bonsai-api → Actions → Rollback → Run workflow
- Saisir la version cible (ex.
v1.2.3) - Choisir
restore_db:no(défaut) — rollback du code uniquement (migrations Flyway compatibles)yes— rollback du code et restauration de la base de données depuis le backup créé avant ce déploiement
Attention :
restore_db=yesécrase toutes les données créées depuis le déploiement à annuler. À réserver aux cas où la migration de schéma est incompatible avec l'ancienne version.
Ce que fait le workflow en coulisse
- Retague l'image
image:vX.Y.Zenimage:latestdans le registry Gitea - (Si
restore_db=yes) Via le socket Docker du runner, arrête l'API et restaure le dump PostgreSQL depuis/opt/backups/bonsai-api/ - Déclenche Watchtower → redéploie le conteneur avec la version rétrogradée
Backups de la base de données
Un backup compressé (pg_dump | gzip) est créé automatiquement avant chaque déploiement de Bonsai API.
- Emplacement sur le serveur :
/opt/backups/bonsai-api/ - Format du nom :
bonsai_v1.2.3_20260531_143000.sql.gz - Rétention : les 10 derniers backups sont conservés, les plus anciens sont supprimés automatiquement
Pour lister les backups disponibles sur le serveur :
ls -lh /opt/backups/bonsai-api/
Pour restaurer manuellement un backup :
VERSION="v1.2.3"
BACKUP_FILE=$(ls -t /opt/backups/bonsai-api/bonsai_${VERSION}_*.sql.gz | head -1)
docker stop bonsai-api
docker exec bonsai-api-db psql -U bonsai postgres \
-c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='bonsai' AND pid != pg_backend_pid();"
docker exec bonsai-api-db dropdb -U bonsai bonsai
docker exec bonsai-api-db createdb -U bonsai bonsai
gunzip -c "$BACKUP_FILE" | docker exec -i bonsai-api-db psql -U bonsai bonsai
docker start bonsai-api
Luz — déploiement par script (SSH direct, sans registre)
Luz ne suit pas le flux registre + Watchtower : le backend et la webapp sont buildés en local puis envoyés au serveur par SSH avec Luz/script/deploy.sh. Il n'y a donc ni docker compose pull, ni image versionnée sur le registre.
Mettre à jour (dev ou prod)
Depuis le repo Luz, en local :
./script/deploy.sh prod # rebuild + envoi + up des 2 images (prod)
./script/deploy.sh prod backend # backend seul
./script/deploy.sh prod webapp # webapp seule
./script/deploy.sh dev # environnement de test
Le script build l'image concernée, la transfère (podman save | gzip | ssh 'docker load'), resynchronise le docker-compose.yml et fait docker compose up -d. Comme l'image rechargée a un nouvel ID sous le même tag, up -d recrée le conteneur. Indisponibilité limitée au redémarrage (quelques secondes).
Commandes de gestion
./script/deploy.sh prod status # docker compose ps
./script/deploy.sh prod logs backend # suit les logs
./script/deploy.sh prod down # arrête le stack (volumes/données conservés)
Rollback
Sans registre, on rejoue une version antérieure depuis le code : se placer sur le commit/tag voulu et redéployer.
git -C ~/Workspace/Luz checkout <tag-ou-commit>
./script/deploy.sh prod
git -C ~/Workspace/Luz checkout main
Base de données (prod). La base prod est persistante et il n'existe pas (encore) de backup automatique comme pour Bonsai/Olhar. Avant un déploiement à risque (migration Flyway destructive), faire un dump manuel :
ssh <serveur> 'docker exec luz-db pg_dump -U luz luz | gzip' > luz_$(date +%F).sql.gzEn environnement test (
dev), la base est réinitialisée à chaque boot : aucun rollback de données à prévoir.
Rollback Olhar (API + PWA, avec ou sans restauration BDD)
Rollback de la PWA
- Aller dans Gitea → Olhar → Actions → Rollback → Run workflow
- Saisir la version cible (ex.
v1.2.3) - Lancer — Watchtower redéploie automatiquement
Rollback de l'API (avec ou sans restauration BDD)
- Aller dans Gitea → Olhar → Actions → Rollback → Run workflow
- Saisir la version cible (ex.
v1.2.3) - Choisir
restore_db:no(défaut) — rollback du code uniquement (migrations Flyway compatibles)yes— rollback du code et restauration de la base de données depuis le backup créé avant ce déploiement
Attention :
restore_db=yesécrase toutes les données créées depuis le déploiement à annuler. À réserver aux cas où la migration de schéma est incompatible avec l'ancienne version.
Les backups sont stockés dans /opt/backups/olhar/ sur le serveur.
Mettre à jour tous les services d'un coup
# Note : luz / dev-luz sont exclus — ils se déploient via Luz/script/deploy.sh (pas de pull registre).
for dir in traefik keycloak gitea bonsai-api bonsai-webapp olhar nextcloud trilium; do
echo "=== $dir ==="
(cd "$dir" && docker compose pull && docker compose up -d)
done
Vérifications après mise à jour
# État de tous les conteneurs
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
# Logs du service mis à jour
docker logs bonsai-webapp --tail 50 -f
# Supprimer les anciennes images devenues inutiles
docker image prune -f