bruno 2d04b90b1a Refactor project documentation and add --check mode
Rebrand from "Docker Scripts" to "Docker Stack Template" and restructure
the README as a step-by-step guide. Add `--check` option to `setup.sh`
for validating system prerequisites with configurable `CMD_DEPEND`.
2026-06-26 16:47:47 -04:00

Docker Stack Template — Auto-Update, Backup, Restore & Déploiement Cron

Template générique et réutilisable pour la maintenance automatisée d'applications Docker (Gitea, ou toute autre app MySQL + volumes) : backup quotidien, mise à jour automatique, restauration et déploiement cron.

🔄 Changez juste DOCKER_APP_NAME=monapp pour adapter à n'importe quelle stack Docker (MySQL + volumes). Voir Étape 3.


📂 Structure du projet

├── setup.sh                  ← 🚀 Installateur tout-en-un
├── docker-scripts.conf       ← ⚙️  Configuration centralisée (DOCKER_APP_NAME, etc.)
├── docker-backup.sh          ← 💾 Backup complet (DB + volumes + config)
├── docker-auto-update.sh     ← 🔄 Mise à jour automatique
├── restore.sh                ← ♻️  Restauration standalone
├── install_cron.sh           ← 🕐 Gestion des crons
└── docker-compose.yml        ← 🐳 Stack Docker de référence

🚀 Guide étape par étape

1. Télécharger le template

# Créer les dossiers standard (FHS)
sudo mkdir -p /opt/docker-scripts /srv/docker
sudo chown -R $USER:$USER /opt/docker-scripts /srv/docker

# Cloner le dépôt
cd /opt
git clone https://git.dracodev.net/Outils/docker-stack-template.git docker-scripts

# Vérifier que tout est là
ls -la /opt/docker-scripts/

2. Configurer pour votre application

C'est l'étape clé : adapter le template à votre application en éditant 3 fichiers.

2a. Copier la configuration dans le dossier de votre app

# Créer le dossier de votre application
mkdir -p /srv/docker/monapp

# Copier la configuration template
cp /opt/docker-scripts/docker-scripts.conf /srv/docker/monapp/

# Copier et adapter le docker-compose si vous partez de l'exemple
cp /opt/docker-scripts/docker-compose.yml /srv/docker/monapp/

2b. Éditer la configuration spécifique à votre app

nano /srv/docker/monapp/docker-scripts.conf

Valeurs obligatoires à changer :

# ─── Prérequis (liste des commandes à vérifier) ──────────────────────────
CMD_DEPEND="git,docker,curl,tar,gzip,crontab"     # 🔧 Adaptez si besoin

# ─── Identité de l'application ────────────────────────────────────────────
DOCKER_APP_NAME="monapp"                          # 🔧 Nom de votre app

# ─── Image Docker ─────────────────────────────────────────────────────────
IMAGE_NAME="monapp/monapp"                        # 🔧 Image Docker utilisée
IMAGE_TAG="latest"                                 # Tag (latest, 1.21, etc.)

# ─── Mots de passe base de données ────────────────────────────────────────
DB_PASSWORD="votre-mot-de-passe-securise"          # 🔧 User MySQL
DB_ROOT_PASSWORD="votre-autre-mot-de-passe"        # 🔧 Root MySQL

# ─── URLs ─────────────────────────────────────────────────────────────────
HEALTH_CHECK_URL="http://localhost:8080"           # 🔧 URL de healthcheck

Valeurs optionnelles à adapter selon votre environnement :

# Sauvegardes
BACKUP_DIR="/NFS/BACKUP/DOCKER/$(hostname)/monapp"  # Emplacement des backups
RETENTION_DAYS="30"                                  # Jours de rétention

# Backup distant (optionnel)
REMOTE_BACKUP_ENABLED=false
REMOTE_BACKUP_HOST="backup.example.com"
REMOTE_BACKUP_PATH="/backups/monapp"

# Notifications (optionnel)
ENABLE_NOTIFICATIONS=false

💡 Les scripts chargent automatiquement la config de l'app si elle existe dans /srv/docker/$DOCKER_APP_NAME/docker-scripts.conf. Ils utilisent la config template de /opt/docker-scripts/ comme fallback.

2c. Adapter le docker-compose.yml

nano /srv/docker/monapp/docker-compose.yml

Points à vérifier :

  • Les noms de services correspondent à la convention ${DOCKER_APP_NAME}_server / ${DOCKER_APP_NAME}_db
  • Les chemins de volumes pointent vers /srv/docker/monapp/data, /srv/docker/monapp/mysql, etc.
  • Les mots de passe dans docker-compose.yml sont cohérents avec ceux de docker-scripts.conf
  • Les healthchecks sont configurés sur les deux services

3. Valider les prérequis

Une fois la configuration faite, vérifiez que votre serveur a tout le nécessaire :

# Vérification des prérequis (lit CMD_DEPEND depuis docker-scripts.conf)
bash /opt/docker-scripts/setup.sh --check

Ce one-liner vérifie automatiquement la présence de chaque commande listée dans CMD_DEPEND (défaut : git,docker,curl,tar,gzip,crontab), ainsi que Docker Compose et le daemon Docker.

Prérequis standards et leur installation :

Outil Pourquoi Installation
git Cloner/mettre à jour les scripts apt install git
docker Conteneurisation docs.docker.com
docker compose Orchestration Plugin inclus avec Docker Engine ≥ 24
curl Healthchecks & notifications apt install curl
tar + gzip Compression des backups Préinstallé sur la plupart des distribs
crontab Planification automatique apt install cron
Droits sudo Accès aux volumes protégés L'utilisateur doit pouvoir sudo

💡 Ajoutez vos propres prérequis dans CMD_DEPEND (ex : CMD_DEPEND="git,docker,curl,tar,gzip,crontab,mysqldump") pour que --check les valide aussi.


4. Installer avec setup.sh

# Installation interactive (recommandée la première fois)
bash /opt/docker-scripts/setup.sh

# Ou forcer sans confirmation
bash /opt/docker-scripts/setup.sh --force

# Ou prévisualiser ce qui sera fait
bash /opt/docker-scripts/setup.sh --dry-run

Ce que setup.sh fait automatiquement :

flowchart TD
    A["🔍 Étape 1 : Vérification prérequis"] --> B["📥 Étape 2 : Clone/màj depuis Git"]
    B --> C["🔑 Étape 3 : Permissions d'exécution"]
    C --> D["📝 Étape 4 : Configuration des logs"]
    D --> E["🔄 Étape 5 : Configuration logrotate"]
    E --> F["🕐 Étape 6 : Installation des crons"]
    F --> G["💾 Option : Premier backup manuel"]

⚠️ Note : setup.sh installe les crons depuis le dossier /opt/docker-scripts/. Pour pointer vers une app spécifique, créez un fichier .env dans le dossier de l'app ou passez DOCKER_APP_NAME=monapp en variable d'environnement.


5. Valider l'installation

5a. Vérifier les crons

# Vérifier que les crons sont bien installés
bash /opt/docker-scripts/install_cron.sh --status

# Ou inspecter directement la crontab
crontab -l | grep -A 3 "DOCKER SCRIPTS"

Vous devriez voir un bloc similaire à :

# >>> MONAPP SCRIPTS (managed by install_cron.sh) <<<
0 2 * * * /opt/docker-scripts/docker-backup.sh >> /var/log/monapp-backup-cron.log 2>&1
0 4 * * * /opt/docker-scripts/docker-auto-update.sh >> /var/log/monapp-update-cron.log 2>&1
# >>> END MONAPP SCRIPTS <<<

5b. Lancer un premier backup manuel

# Premier backup réel
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/docker-backup.sh

# Vérifier le résultat
ls -la /NFS/BACKUP/DOCKER/$(hostname)/monapp/

5c. Vérifier les logs

# Logs du backup
tail -20 /var/log/monapp-backup.log

# Logs de l'auto-update
tail -20 /var/log/monapp-update.log

# Logs cron
tail -20 /var/log/monapp-backup-cron.log

5d. Tester l'auto-update

# Test manuel de la mise à jour automatique
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/docker-auto-update.sh

5e. Tester la restauration (optionnel mais recommandé)

# Lister les backups disponibles
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/restore.sh

# Dry-run d'une restauration (vérifie sans exécuter)
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/restore.sh \
  /NFS/BACKUP/DOCKER/$(hostname)/monapp/monapp-backup-AAAAMMJJ-HHMMSS --dry-run

6. Opérations quotidiennes

Une fois installé, le système tourne automatiquement :

flowchart LR
    subgraph Daily["📅 Quotidien automatique (cron)"]
        direction TB
        A["🕐 2h00 — Backup"] --> B["💾 Sauvegarde complète<br/>(DB + volumes + config)"]
        B --> C["🧹 Nettoyage vieux backups"]
        C --> D["☁️ Sync distante (si activée)"]

        E["🕐 4h00 — Auto-update"] --> F{"Nouvelle image Docker ?"}
        F -->|"Non"| G["✅ Rien à faire"]
        F -->|"Oui"| H["💾 Backup DB rapide"]
        H --> I["🚀 docker compose up -d"]
        I --> J{"Santé OK ?"}
        J -->|"Oui"| K["✅ Mise à jour OK"]
        J -->|"Non"| L["🔄 Rollback automatique"]
    end

Commandes utiles au quotidien

# ─── Vérifier l'état ───────────────────────────────────────────────────
bash /opt/docker-scripts/install_cron.sh --status   # État des crons
docker compose -f /srv/docker/monapp/docker-compose.yml ps  # État des conteneurs
df -h /NFS/BACKUP/DOCKER/$(hostname)/monapp          # Espace disque backups

# ─── Backup manuel ─────────────────────────────────────────────────────
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/docker-backup.sh

# ─── Restaurer un backup ───────────────────────────────────────────────
# Lister les backups
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/restore.sh
# Restaurer le plus récent
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/restore.sh \
  $(ls -td /NFS/BACKUP/DOCKER/$(hostname)/monapp/monapp-backup-* | head -1)

# ─── Mettre à jour les scripts ─────────────────────────────────────────
bash /opt/docker-scripts/setup.sh --update

# ─── Désinstaller les crons ────────────────────────────────────────────
bash /opt/docker-scripts/install_cron.sh --uninstall

⚙️ Référence de configuration

Fichier docker-scripts.conf

Tous les paramètres sont centralisés dans docker-scripts.conf. Les scripts utilisent un système de surcharge à deux niveaux :

  1. Config globale (/opt/docker-scripts/docker-scripts.conf) — valeurs par défaut
  2. Config applicative (/srv/docker/<app>/docker-scripts.conf) — surcharge la globale

Les variables d'environnement prennent le dessus sur les deux fichiers.

# Exemple : changer le dossier de backup à la volée
BACKUP_DIR=/mnt/big-disk/monapp DOCKER_APP_NAME=monapp bash /opt/docker-scripts/docker-backup.sh

# Exemple : backup avec arrêt des conteneurs
STOP_CONTAINERS=true DOCKER_APP_NAME=monapp bash /opt/docker-scripts/docker-backup.sh

# Exemple : backup + sync distante
REMOTE_BACKUP_ENABLED=true DOCKER_APP_NAME=monapp bash /opt/docker-scripts/docker-backup.sh

Variables clés

Variable Défaut Description
CMD_DEPEND git,docker,curl,tar,gzip,crontab Liste des prérequis pour setup.sh --check
DOCKER_APP_NAME gitea 🔧 Principal — nom de l'application (définit tous les dérivés)
IMAGE_NAME gitea/gitea 🔧 Image Docker à déployer
IMAGE_TAG latest Tag de l'image
COMPOSE_DIR /srv/docker/$DOCKER_APP_NAME Dossier docker-compose
BACKUP_DIR /NFS/BACKUP/DOCKER/$HOSTNAME/$DOCKER_APP_NAME Destination backups
DB_NAME $DOCKER_APP_NAME Nom base de données
DB_PASSWORD change_me_in_production 🔧 Mot de passe user MySQL
DB_ROOT_PASSWORD change_me_in_production 🔧 Mot de passe root MySQL
HEALTH_CHECK_URL http://localhost:3000 🔧 URL de healthcheck
RETENTION_DAYS 30 Rétention des backups (jours)
CRON_BACKUP_SCHEDULE 0 2 * * * Horaire backup quotidien
CRON_UPDATE_SCHEDULE 0 4 * * * Horaire mise à jour quotidienne

🛠️ Référence des scripts

setup.sh — Installation complète

bash setup.sh              # Installation interactive
bash setup.sh --force      # Sans confirmation
bash setup.sh --update     # Mise à jour des scripts (git pull)
bash setup.sh --dry-run    # Aperçu sans rien installer

docker-backup.sh — Backup complet

Sauvegarde tout : DB MySQL + volumes Docker + configuration + script restore.

DOCKER_APP_NAME=monapp bash docker-backup.sh

Structure d'un backup :

/NFS/BACKUP/DOCKER/serveur/monapp/
└── monapp-backup-20260626-020000/
    ├── monapp-db.sql.gz         ← Dump MySQL (compressé)
    ├── monapp-data.tar.gz       ← Volume /data
    ├── monapp-mysql.tar.gz      ← Volume MySQL
    ├── docker-compose.yml       ← Stack Docker
    ├── app.ini                  ← Configuration applicative
    ├── restore.sh               ← ⭐ Script de restauration automatique
    └── backup-info.txt          ← Métadonnées

restore.sh — Restauration standalone

# Lister les backups disponibles
DOCKER_APP_NAME=monapp bash restore.sh

# Restauration interactive
DOCKER_APP_NAME=monapp bash restore.sh /chemin/backup

# Dry-run (vérifier sans exécuter)
DOCKER_APP_NAME=monapp bash restore.sh /chemin/backup --dry-run

# Forcée (sans confirmation)
DOCKER_APP_NAME=monapp bash restore.sh /chemin/backup --force

Étapes de restauration :

  1. Arrêt des conteneurs existants
  2. Création des répertoires cibles
  3. Restauration des volumes (MySQL, data)
  4. Copie du docker-compose.yml et de la config
  5. Démarrage des conteneurs
  6. Restauration de la base de données + redémarrage final

docker-auto-update.sh — Mise à jour automatique

DOCKER_APP_NAME=monapp bash docker-auto-update.sh

Fonctionnement :

  1. Récupère le digest SHA256 de l'image actuelle
  2. docker compose pull pour la dernière version
  3. Si le digest est identique → rien à faire
  4. Si différent → backup DB rapide → déploiement → healthcheck → rollback si échec
  5. Nettoyage des anciennes images

Notifications (optionnel) :

# Telegram
ENABLE_NOTIFICATIONS=true NOTIFY_METHOD=telegram \
  TELEGRAM_BOT_TOKEN=xxx TELEGRAM_CHAT_ID=xxx \
  DOCKER_APP_NAME=monapp bash docker-auto-update.sh

# ntfy.sh
ENABLE_NOTIFICATIONS=true NOTIFY_METHOD=ntfy \
  NTPY_TOPIC=mon-topic \
  DOCKER_APP_NAME=monapp bash docker-auto-update.sh

install_cron.sh — Gestion des crons

bash install_cron.sh              # Installation interactive
bash install_cron.sh --force      # Sans confirmation
bash install_cron.sh --dry-run    # Aperçu
bash install_cron.sh --uninstall  # Retirer du cron (bloc marqué uniquement)
bash install_cron.sh --status     # Vérifier l'état

🔒 Sécurité

⚠️ Les mots de passe dans docker-scripts.conf et docker-compose.yml utilisent des valeurs par défaut. Changez-les avant toute mise en production :

# Dans /srv/docker/monapp/docker-scripts.conf
DB_ROOT_PASSWORD=votre-mot-de-passe-securise
DB_PASSWORD=votre-autre-mot-de-passe
# Dans /srv/docker/monapp/docker-compose.yml
environment:
  MYSQL_ROOT_PASSWORD: votre-mot-de-passe-securise
  MYSQL_PASSWORD: votre-autre-mot-de-passe

📊 Logs

Script Log
Backup /var/log/<app>-backup.log
Auto-update /var/log/<app>-update.log
Cron backup /var/log/<app>-backup-cron.log
Cron update /var/log/<app>-update-cron.log

La rotation des logs est configurée automatiquement par setup.sh via logrotate (rotation hebdomadaire, 12 semaines de rétention, compression).


🔒 Lock files

Pour éviter les exécutions concurrentes (backup + update simultanés), chaque script utilise un lock file dans /tmp :

  • /tmp/<app>-backup.lock
  • /tmp/<app>-auto-update.lock

Un lock stale (PID inexistant) est automatiquement nettoyé.


🔧 Dépannage

Le backup échoue par manque d'espace

# Vérifier l'espace
df -h /NFS/BACKUP/DOCKER/$(hostname)/monapp

# Nettoyer les vieux backups (garde les 10 plus récents)
ls -t /NFS/BACKUP/DOCKER/$(hostname)/monapp/monapp-backup-* | tail -n +11 | xargs rm -rf

L'auto-update échoue

# Vérifier les logs
tail -50 /var/log/monapp-update.log

# Tester manuellement
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/docker-auto-update.sh

Les crons ne s'exécutent pas

# Vérifier l'état
bash /opt/docker-scripts/install_cron.sh --status

# Vérifier les logs cron système
grep CRON /var/log/syslog | tail -20

# Réinstaller les crons
bash /opt/docker-scripts/install_cron.sh --force

Restauration d'urgence

# Lister les backups
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/restore.sh

# Restaurer le plus récent
DOCKER_APP_NAME=monapp bash /opt/docker-scripts/restore.sh \
  $(ls -td /NFS/BACKUP/DOCKER/$(hostname)/monapp/monapp-backup-* | head -1)

Mettre à jour les scripts eux-mêmes

bash /opt/docker-scripts/setup.sh --update

💡 Pour automatiser la mise à jour des scripts, ajoutez cette ligne à la crontab :

0 3 * * 0 bash /opt/docker-scripts/setup.sh --update --force

🏗️ Architecture

flowchart TB
    subgraph Config["⚙️ Configuration"]
        GLOBAL["/opt/docker-scripts/docker-scripts.conf<br/>Template global"]
        APP["/srv/docker/monapp/docker-scripts.conf<br/>Config applicative (prioritaire)"]
    end

    subgraph Scripts["🛠️ Scripts core"]
        BACKUP["docker-backup.sh<br/>💾 Backup quotidien"]
        UPDATE["docker-auto-update.sh<br/>🔄 Mise à jour auto"]
        RESTORE["restore.sh<br/>♻️ Restauration"]
    end

    subgraph Deploy["🚀 Déploiement"]
        SETUP["setup.sh<br/>Installateur complet"]
        CRON["install_cron.sh<br/>Gestion crontab"]
    end

    subgraph Runtime["⚡ Runtime"]
        CRONTAB["Crontab<br/>Backup 2h → Update 4h"]
        DOCKER["Docker Compose<br/>App + MySQL"]
    end

    subgraph Storage["💾 Stockage"]
        LOCAL["Backups locaux<br/>/NFS/BACKUP/..."]
        REMOTE["Backup distant<br/>rsync / SCP"]
    end

    GLOBAL --> Scripts
    APP --> Scripts
    SETUP --> CRON
    SETUP --> DOCKER
    CRON --> CRONTAB
    CRONTAB --> BACKUP
    CRONTAB --> UPDATE
    BACKUP --> LOCAL
    BACKUP --> REMOTE
    RESTORE --> LOCAL
    RESTORE --> DOCKER
    UPDATE --> DOCKER
S
Description
Scripts automatisés pour Gitea Docker : auto-update et backup
Readme
221 KiB
Languages
Shell 100%