# 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](#3--configurer-pour-votre-application). --- ## 📂 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 ```bash # 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 ```bash # 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 ```bash nano /srv/docker/monapp/docker-scripts.conf ``` **Valeurs obligatoires à changer :** ```bash # ─── 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 :** ```bash # 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 ```bash 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 : ```bash # 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](https://docs.docker.com/engine/install/) | | `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 ```bash # 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 :** ```mermaid 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 ```bash # 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 à : ```cron # >>> 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 ```bash # 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 ```bash # 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 ```bash # 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é) ```bash # 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** : ```mermaid flowchart LR subgraph Daily["📅 Quotidien automatique (cron)"] direction TB A["🕐 2h00 — Backup"] --> B["💾 Sauvegarde complète
(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 ```bash # ─── 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//docker-scripts.conf`) — surcharge la globale Les variables d'environnement **prennent le dessus** sur les deux fichiers. ```bash # 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 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. ```bash 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 ```bash # 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 ```bash 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) :** ```bash # 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 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 :** ```bash # Dans /srv/docker/monapp/docker-scripts.conf DB_ROOT_PASSWORD=votre-mot-de-passe-securise DB_PASSWORD=votre-autre-mot-de-passe ``` ```yaml # 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/-backup.log` | | Auto-update | `/var/log/-update.log` | | Cron backup | `/var/log/-backup-cron.log` | | Cron update | `/var/log/-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/-backup.lock` - `/tmp/-auto-update.lock` Un lock stale (PID inexistant) est automatiquement nettoyé. --- ## 🔧 Dépannage ### Le backup échoue par manque d'espace ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 bash /opt/docker-scripts/setup.sh --update ``` > 💡 Pour automatiser la mise à jour des scripts, ajoutez cette ligne à la crontab : > ```cron > 0 3 * * 0 bash /opt/docker-scripts/setup.sh --update --force > ``` --- ## 🏗️ Architecture ```mermaid flowchart TB subgraph Config["⚙️ Configuration"] GLOBAL["/opt/docker-scripts/docker-scripts.conf
Template global"] APP["/srv/docker/monapp/docker-scripts.conf
Config applicative (prioritaire)"] end subgraph Scripts["🛠️ Scripts core"] BACKUP["docker-backup.sh
💾 Backup quotidien"] UPDATE["docker-auto-update.sh
🔄 Mise à jour auto"] RESTORE["restore.sh
♻️ Restauration"] end subgraph Deploy["🚀 Déploiement"] SETUP["setup.sh
Installateur complet"] CRON["install_cron.sh
Gestion crontab"] end subgraph Runtime["⚡ Runtime"] CRONTAB["Crontab
Backup 2h → Update 4h"] DOCKER["Docker Compose
App + MySQL"] end subgraph Storage["💾 Stockage"] LOCAL["Backups locaux
/NFS/BACKUP/..."] REMOTE["Backup distant
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 ```