最后活跃于 1 month ago

Full backup zip + all compose file ! Compose Docker + Report Html

修订 f699ffdac8fb61441a0fc4fe2d5ef8c33ea63cfe

Backup-Home-docker.tar.gz.sh 原始文件
1#!/bin/bash
2
3#############################
4# CONFIG
5#############################
6
7# Backup complet des data docker , casaos et portainer
8# avec liste de tous les compose files des containers classés par répertoire.
9
10
11# Répertoire contenant tes containers
12SOURCE_DIR="/home/docker"
13
14# Répertoire où stocker les sauvegardes
15BACKUP_DIR="/home/backup/docker"
16
17# Nombre max de backups à conserver (dossiers datés)
18MAX_BACKUPS=3
19
20# Date interne (pour logs / JSON)
21DATE_RAW="$(date +'%Y%m%d_%H%M%S')"
22# Date pour le dossier de backup (format humain demandé)
23DATE_DIR="$(date +'%Y.%m.%d_%H-%M-%S')"
24
25# Dossier de ce backup
26RUN_DIR="$BACKUP_DIR/$DATE_DIR"
27
28# Fichiers TAR dans le dossier de ce backup
29BACKUP_FILE="$RUN_DIR/docker_backup.tar.gz"
30CASAOS_FULL_TAR="$RUN_DIR/casaos_full_backup.tar.gz"
31
32# Dossier où l'on met les compose / configs
33CONFIG_DIR="$RUN_DIR"
34
35# Dossiers à exclure (chemins relatifs à $SOURCE_DIR pour le tar Docker)
36EXCLUDE_DIRS=(
37 "docker_var_lib"
38 "1_Backups"
39 "casaos_data/*"
40 "nginx_proxy/data/logs/*"
41 "yt-dl/video/*"
42)
43
44# LOGS
45LOG_FILE="/var/log/docker_backup.log"
46
47#############################
48# COULEURS
49#############################
50NC="\e[0m"
51GREEN="\e[32m"
52YELLOW="\e[33m"
53CYAN="\e[36m"
54RED="\e[31m"
55
56#############################
57# FONCTIONS
58#############################
59
60log_message() {
61 local msg="$1"
62 local now
63 now="$(date +'%Y-%m-%d %H:%M:%S')"
64 echo "$now - $msg" >> "$LOG_FILE"
65 echo -e "$now - $msg"
66}
67
68format_time() {
69 local t=$1
70 ((h=t/3600))
71 ((m=(t%3600)/60))
72 ((s=t%60))
73 printf "%02d:%02d:%02d\n" $h $m $s
74}
75
76check_pigz() {
77 if ! command -v pigz >/dev/null 2>&1; then
78 echo -e "${YELLOW}pigz n'est pas installé. Voulez-vous l’installer ? (y/n)${NC}"
79 read rep
80 if [ "$rep" = "y" ]; then
81 sudo apt update && sudo apt install -y pigz || {
82 echo -e "${RED}Échec de l’installation de pigz. Abandon.${NC}"
83 exit 1
84 }
85 else
86 echo -e "${RED}pigz est requis pour ce script. Abandon.${NC}"
87 exit 1
88 fi
89 fi
90}
91
92rotate_backups() {
93 log_message "Rotation des anciens backups (conserver les $MAX_BACKUPS plus récents)..."
94
95 # On ne garde que les dossiers datés dans BACKUP_DIR
96 mapfile -t backups_dirs < <(ls -1td "$BACKUP_DIR"/*/ 2>/dev/null || true)
97
98 if [ "${#backups_dirs[@]}" -gt "$MAX_BACKUPS" ]; then
99 for d in "${backups_dirs[@]:$MAX_BACKUPS}"; do
100 log_message "Suppression ancien backup (dossier) : $d"
101 rm -rf "$d"
102 done
103 fi
104}
105
106get_size() {
107 du -sh "$1" 2>/dev/null | awk '{print $1}'
108}
109
110#############################
111# DÉBUT SCRIPT
112#############################
113
114SECONDS=0
115
116check_pigz
117
118mkdir -p "$RUN_DIR"
119touch "$LOG_FILE"
120
121echo -e "${CYAN}=== Backup Docker + Configs (Portainer / CasaOS) ===${NC}"
122log_message "Début sauvegarde Docker + configs Portainer & CasaOS..."
123log_message "Dossier de backup : $RUN_DIR"
124
125##############################################
126# 1) Sauvegarde TAR Docker via pigz + exclusions
127##############################################
128log_message "Création de l’archive Docker : $BACKUP_FILE"
129
130EXCLUDE_ARGS=(
131 "--exclude=*.log"
132 "--exclude=.composer"
133 "--exclude=.aptitude"
134 "--exclude=.cache"
135 "--exclude=.cmake"
136 "--exclude=.yarn"
137 "--exclude=.w3m"
138 "--exclude=.pip"
139 "--exclude=.pm2"
140 "--exclude=.pm"
141 "--exclude=.bundle"
142 "--exclude=.gem"
143 "--exclude=.cpan"
144 "--exclude=.cpanm"
145 "--exclude=.git"
146 "--exclude=.local"
147 "--exclude=.npm"
148 "--exclude=.nvm"
149 "--exclude=.rvm"
150 "--exclude=node_modules"
151 "--exclude=lost+found"
152)
153
154for d in "${EXCLUDE_DIRS[@]}"; do
155 EXCLUDE_ARGS+=( "--exclude=$d" )
156done
157
158tar -cf "$BACKUP_FILE" -I pigz \
159 --directory="$SOURCE_DIR" \
160 "${EXCLUDE_ARGS[@]}" \
161 . 2>> "$LOG_FILE"
162
163if [ $? -ne 0 ]; then
164 log_message "ERREUR lors de la création du tar Docker."
165 echo -e "${RED}Erreur lors de la création de l’archive Docker.${NC}"
166 exit 1
167fi
168
169##############################################
170# 2) Extraction des docker-compose
171# - CasaOS: RUN_DIR/casaos/<container>/
172# - Docker: RUN_DIR/docker/<container>/
173##############################################
174
175log_message "Extraction des docker-compose CasaOS..."
176if [ -d "$SOURCE_DIR/casaos_data" ]; then
177 find "$SOURCE_DIR/casaos_data" -maxdepth 3 -type f -name "docker-compose.y*ml" | while read file; do
178 container_name=$(basename "$(dirname "$file")")
179 dest_dir="$CONFIG_DIR/casaos/$container_name"
180 mkdir -p "$dest_dir"
181 cp "$file" "$dest_dir/"
182 log_message " [CasaOS] → Compose trouvé : $file"
183 done
184fi
185
186log_message "Extraction des docker-compose Docker (hors casaos_data & dossiers exclus)..."
187find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
188 ! -path "$SOURCE_DIR/casaos_data/*" \
189 ! -path "$SOURCE_DIR/docker_var_lib/*" \
190 2>/dev/null | while read file; do
191 container_name=$(basename "$(dirname "$file")")
192 dest_dir="$CONFIG_DIR/Compose/$container_name"
193 mkdir -p "$dest_dir"
194 cp "$file" "$dest_dir/"
195 log_message " [Docker] → Compose trouvé : $file"
196 done
197
198##############################################
199# 3) Config Portainer (full)
200##############################################
201PORTAINER_CONFIG_DIR="$CONFIG_DIR/portainer"
202PORTAINER_FILES=0
203
204if docker volume inspect portainer_data >/dev/null 2>&1; then
205 log_message "Sauvegarde config Portainer..."
206 mkdir -p "$PORTAINER_CONFIG_DIR"
207 cp -r /var/lib/docker/volumes/portainer_data/_data/* "$PORTAINER_CONFIG_DIR/" 2>>"$LOG_FILE"
208 PORTAINER_FILES=$(find "$PORTAINER_CONFIG_DIR" -type f 2>/dev/null | wc -l)
209else
210 PORTAINER_CONFIG_DIR=""
211fi
212
213##############################################
214# 4) Config CasaOS (full + tar.gz)
215##############################################
216CASAOS_CONFIG_DIR="$CONFIG_DIR/casaos/full_config"
217
218if [ -d "/var/lib/casaos" ]; then
219 log_message "Sauvegarde config CasaOS (full vers $CASAOS_CONFIG_DIR)..."
220 mkdir -p "$CASAOS_CONFIG_DIR"
221 cp -r /var/lib/casaos/* "$CASAOS_CONFIG_DIR/" 2>>"$LOG_FILE"
222fi
223
224# Création du second tar.gz CasaOS FULL (config + volumes casaos_data)
225if [ -d "/var/lib/casaos" ] || [ -d "$SOURCE_DIR/casaos_data" ]; then
226 CASAOS_TAR_SOURCES=()
227 [ -d "/var/lib/casaos" ] && CASAOS_TAR_SOURCES+=( "/var/lib/casaos" )
228 [ -d "$SOURCE_DIR/casaos_data" ] && CASAOS_TAR_SOURCES+=( "$SOURCE_DIR/casaos_data" )
229
230 if [ "${#CASAOS_TAR_SOURCES[@]}" -gt 0 ]; then
231 log_message "Création de l’archive CASAOS FULL : $CASAOS_FULL_TAR"
232 tar -cf "$CASAOS_FULL_TAR" -I pigz "${CASAOS_TAR_SOURCES[@]}" 2>>"$LOG_FILE"
233 if [ $? -ne 0 ]; then
234 log_message "ERREUR lors de la création du tar CasaOS."
235 echo -e "${RED}Erreur lors de la création de l’archive CasaOS.${NC}"
236 fi
237 fi
238fi
239
240##############################################
241# 5) Comptages finaux (sur le backup courant)
242##############################################
243
244# Compose dans le backup (docker + CasaOS compose seulement)
245CASAOS_COMPOSE_BACKUP=$(find "$CONFIG_DIR/casaos" -maxdepth 3 -type f -name "docker-compose.y*ml" ! -path "$CASAOS_CONFIG_DIR/*" 2>/dev/null | wc -l)
246DOCKER_COMPOSE_BACKUP=$(find "$CONFIG_DIR/docker" -type f -name "docker-compose.y*ml" 2>/dev/null | wc -l)
247
248# Compose dans le dossier source (uniquement /home/docker/<container>/docker-compose.*)
249SOURCE_COMPOSE_COUNT=$(find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
250 ! -path "$SOURCE_DIR/casaos_data/*" \
251 ! -path "$SOURCE_DIR/docker_var_lib/*" \
252 2>/dev/null | wc -l)
253
254# Containers Docker "valides"
255CONTAINERS_DOCKER=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
256 ! -path "$SOURCE_DIR/casaos_data" \
257 ! -path "$SOURCE_DIR/docker_var_lib" \
258 ! -path "$SOURCE_DIR/portainer" 2>/dev/null | wc -l)
259
260# Rotation des anciens backups (par dossiers)
261rotate_backups
262
263# Nombre total de sets de backup (dossiers datés)
264TOTAL_BACKUP_SETS=$(ls -1d "$BACKUP_DIR"/*/ 2>/dev/null | wc -l)
265
266# Oldest / newest backup set
267mapfile -t CURRENT_SETS < <(ls -1d "$BACKUP_DIR"/*/ 2>/dev/null | sort)
268OLDEST_DIR="${CURRENT_SETS[0]}"
269NEWEST_DIR="${CURRENT_SETS[${#CURRENT_SETS[@]}-1]}"
270
271DURATION="$(format_time $SECONDS)"
272
273# Tailles des backups courants
274TAR_SIZE=$(get_size "$BACKUP_FILE")
275CONFIG_SIZE=$(get_size "$CONFIG_DIR")
276DOCKER_CONFIG_SIZE=$(get_size "$CONFIG_DIR/docker")
277
278# CasaOS full config size (copie dans RUN_DIR/casaos/full_config)
279if [ -d "$CASAOS_CONFIG_DIR" ]; then
280 CASAOS_CONFIG_SIZE=$(get_size "$CASAOS_CONFIG_DIR")
281else
282 CASAOS_CONFIG_SIZE=""
283fi
284
285# CasaOS FULL TAR size
286if [ -f "$CASAOS_FULL_TAR" ]; then
287 CASAOS_FULL_TAR_SIZE=$(get_size "$CASAOS_FULL_TAR")
288else
289 CASAOS_FULL_TAR_SIZE=""
290fi
291
292# Portainer full config size
293if [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ]; then
294 PORTAINER_CONFIG_SIZE=$(get_size "$PORTAINER_CONFIG_DIR")
295else
296 PORTAINER_CONFIG_SIZE=""
297fi
298
299##############################################
300# 6) RÉSUMÉS
301##############################################
302
303echo -e "${GREEN}===== BACKUP TERMINÉ =====${NC}"
304echo -e "${CYAN}Dossier backup courant : ${YELLOW}$RUN_DIR${NC}"
305
306##############################################
307# LISTE DES DOSSIERS DOCKER PAR TAILLE (ASCII)
308##############################################
309
310echo -e "\n${CYAN}----- LISTE/TAILLE DES RÉPERTOIRES DOCKER -----${NC}"
311
312DOCKER_DIRS=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
313 ! -path "$SOURCE_DIR/casaos_data" \
314 ! -path "$SOURCE_DIR/docker_var_lib" \
315 ! -path "$SOURCE_DIR/portainer" 2>/dev/null)
316
317if [ -z "$DOCKER_DIRS" ]; then
318 echo -e "${YELLOW}(Aucun dossier Docker trouvé)${NC}"
319else
320 echo -e "┌──────────────────────────┬─────────┬────────────────────────────────────────┐"
321 printf "│ %-24s │ %-7s │ %-38s │\n" "Container" "Taille" "Chemin"
322 echo -e "├──────────────────────────┼─────────┼────────────────────────────────────────┤"
323 du -sh $DOCKER_DIRS 2>/dev/null | sort -hr | while read -r size path; do
324 name=$(basename "$path")
325 printf "│ %-24s │ %-7s │ %-38s │\n" "$name" "$size" "$path"
326 done
327 echo -e "└──────────────────────────┴─────────┴────────────────────────────────────────┘"
328fi
329
330#################################
331# DOCKER
332#################################
333echo -e "${CYAN}\n----- DOCKER -----${NC}"
334echo -e "${CYAN}Containers Docker détectés : ${GREEN}$CONTAINERS_DOCKER${NC}"
335echo -e "${CYAN}Compose source (Docker) : ${GREEN}$SOURCE_COMPOSE_COUNT${NC}"
336echo -e "${CYAN}Compose backup (Docker) : ${GREEN}$DOCKER_COMPOSE_BACKUP${NC}"
337echo -e "${CYAN}Dossier compose Docker : ${YELLOW}$CONFIG_DIR/docker${NC}"
338echo -e "${CYAN}Taille compose Docker : ${GREEN}$DOCKER_CONFIG_SIZE${NC}"
339
340#################################
341# CASAOS (si présent)
342#################################
343if [ -d "$CONFIG_DIR/casaos" ] || [ -f "$CASAOS_FULL_TAR" ]; then
344 echo -e "${CYAN}\n----- CASAOS -----${NC}"
345 echo -e "${CYAN}Compose CasaOS backup : ${GREEN}$CASAOS_COMPOSE_BACKUP${NC}"
346 echo -e "${CYAN}Dossier CasaOS backup : ${YELLOW}$CONFIG_DIR/casaos${NC}"
347 [ -n "$CASAOS_CONFIG_SIZE" ] && echo -e "${CYAN}Taille config CasaOS (full) : ${GREEN}$CASAOS_CONFIG_SIZE${NC}"
348 if [ -f "$CASAOS_FULL_TAR" ]; then
349 echo -e "${CYAN}Tar CasaOS FULL : ${YELLOW}$CASAOS_FULL_TAR${NC}"
350 echo -e "${CYAN}Taille tar CasaOS FULL : ${GREEN}$CASAOS_FULL_TAR_SIZE${NC}"
351 fi
352fi
353
354#################################
355# PORTAINER (si présent)
356#################################
357if [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ]; then
358 echo -e "${CYAN}\n----- PORTAINER -----${NC}"
359 echo -e "${CYAN}Fichiers config Portainer : ${GREEN}$PORTAINER_FILES${NC}"
360 echo -e "${CYAN}Dossier Portainer backup : ${YELLOW}$PORTAINER_CONFIG_DIR${NC}"
361 [ -n "$PORTAINER_CONFIG_SIZE" ] && echo -e "${CYAN}Taille Portainer (full) : ${GREEN}$PORTAINER_CONFIG_SIZE${NC}"
362fi
363
364#################################
365# GLOBAL
366#################################
367echo -e "${CYAN}\n----- GLOBAL -----${NC}"
368echo -e "${CYAN}Nombre de sets de backup : ${GREEN}$TOTAL_BACKUP_SETS${NC}"
369echo -e "${CYAN}Oldest backup dir : ${YELLOW}${OLDEST_DIR:-N/A}${NC}"
370echo -e "${CYAN}Newest backup dir : ${YELLOW}${NEWEST_DIR:-N/A}${NC}"
371echo -e "${CYAN}Taille archive Docker tar.gz : ${GREEN}$TAR_SIZE${NC}"
372[ -f "$CASAOS_FULL_TAR" ] && echo -e "${CYAN}Taille archive CasaOS tar.gz : ${GREEN}$CASAOS_FULL_TAR_SIZE${NC}"
373echo -e "${CYAN}Taille dossier backup courant: ${GREEN}$CONFIG_SIZE${NC}"
374echo -e "${CYAN}Archive Docker courante : ${YELLOW}$BACKUP_FILE${NC}"
375[ -f "$CASAOS_FULL_TAR" ] && echo -e "${CYAN}Archive CasaOS courante : ${YELLOW}$CASAOS_FULL_TAR${NC}"
376echo -e "${CYAN}Durée totale : ${GREEN}$DURATION${NC}"
377
378#################################
379# JSON (optionnel : ./script.sh --json)
380#################################
381if [ "$1" = "--json" ]; then
382 echo ""
383 echo "{"
384 echo " \"date_raw\": \"$DATE_RAW\","
385 echo " \"date_dir\": \"$DATE_DIR\","
386 echo " \"run_dir\": \"$RUN_DIR\","
387 echo " \"docker_backup_file\": \"$BACKUP_FILE\","
388 echo " \"docker_backup_size\": \"$TAR_SIZE\","
389 echo " \"casaos_full_backup_file\": \"${CASAOS_FULL_TAR:-}\","
390 echo " \"casaos_full_backup_size\": \"${CASAOS_FULL_TAR_SIZE:-}\","
391 echo " \"docker\": {"
392 echo " \"containers\": $CONTAINERS_DOCKER,"
393 echo " \"compose_source\": $SOURCE_COMPOSE_COUNT,"
394 echo " \"compose_backup\": $DOCKER_COMPOSE_BACKUP"
395 echo " },"
396 echo " \"casaos\": {"
397 echo " \"compose_backup\": $CASAOS_COMPOSE_BACKUP"
398 echo " },"
399 echo " \"portainer\": {"
400 echo " \"files\": $PORTAINER_FILES"
401 echo " },"
402 echo " \"backup_sets\": $TOTAL_BACKUP_SETS,"
403 echo " \"oldest_backup_dir\": \"${OLDEST_DIR:-}\","
404 echo " \"newest_backup_dir\": \"${NEWEST_DIR:-}\","
405 echo " \"duration\": \"$DURATION\""
406 echo "}"
407fi
408