OpenMediaVault : Sauvegarde des containers Docker

Lors de mon article sur l’organisation de mes sauvegardes sur mon NAS OpenMediaVault, il me manquait la bonne façon de sauvegarder les containers Docker.

Je sauvegardais avec rsync le répertoire où se trouve Docker, il y avait des milliers de fichiers, et je ne pense pas que j’aurais pu faire grand chose de cette sauvegarde en cas de problème ! 🙁

J’ai donc cherché du côté de Docker, et sans surprise Docker propose sa propre solution pour la sauvegarde des containers. Les principales commandes sont expliquées sur ce schéma :

Les principales commandes pour la sauvegarde & la restoration

L’idée est donc de créer une image de chaque container (commande COMMIT), puis de les sauvegarder au format .tar (commande SAVE). On voit sur l’image les commandes LOAD et RUN qu’il faudra utiliser dans l’autre sens pour la restauration.

Ensuite, il fallait que je copie ces fichiers .tar sur mon PC à l’aide de rsync, puisque j’ai déjà un serveur rsync qui tourne sur ce dernier. Il ne restait plus qu’à faire un peu de ménage avec ces images et fichiers créés sur le NAS ou sur le PC pour avoir quelque chose de propre.

J’ai donc préparé un script qui fait tout ça, que j’ai ensuite ajouté en tâche crontab au système. Ainsi mes containers sont sauvegardés chaque semaine.

Voyons voir un peu tout cela en détail.

Dans l’explication ci-dessous, je ne traite que d’un seul container comme exemple (Nextcloud), il suffit d’appliquer les mêmes actions pour chaque container utilisé sur votre serveur que vous souhaitez sauvegarder.

Nous avons d’abord besoin d’identifier le nom de l’image de notre container. Pour cela, on va utiliser la commande docker images et noter le REPOSITORY soit linuxserver/nextcloud ci-dessous :

pascal@odroidhc2:~$ sudo docker images
REPOSITORY                           TAG       IMAGE ID       CREATED        SIZE
linuxserver/nextcloud                latest    70e33dd606b8   3 months ago   330MB

Script – première partie

Dans un premier temps, on va définir quelques variables qui nous seront utiles dans le script : d’abord un répertoire où créer les fichiers image (disque externe du NAS OMV), ainsi qu’une variable pour ajouter un « time-tamp » aux fichiers que l’on va créer ; puis le nom de l’image (le REPOSITORY noté ci-dessus), qui nous permettra d’aller chercher le container ID, et enfin le nom de l’image.

# init des variables
backup_dir="/srv/dev-disk-by-label-DATA/Docker-Containers-Backup/"
now=$(date +%d-%m-%Y-%H-%M-%S)
nextcloud_imgname="linuxserver/nextcloud"
nextcloud_imgid=$(docker ps -a -f "ancestor=$nextcloud_imgname" -q -l)
bck_nextcloud_imgname=backup_nextcloud

Une fois ceci fait, on peut créer une image du container :

# Création de l'image
docker commit -p "$nextcloud_imgid" "$bck_nextcloud_imgname"

Puis on copie cette image au format .tar dans un dossier du NAS défini plus haut :

# Sauvegarde de l'image sur le disque externe du NAS
docker save -o  "$backup_dir""$bck_nextcloud_imgname"_"$now".tar "$bck_nextcloud_imgname"

Puis on compresse l’archive :

# Compression des archives
gzip "$backup_dir"*.tar

Il ne reste plus qu’à envoyer l’archive sur le PC, où tourne un serveur rsync.

Serveur SSH sur PC

Pour éviter d’avoir à entrer un mot de passe lorsque le script arrive à cette étape, il m’a fallu activer le serveur SSH sur le PC :

pascal@SH87R:~$ sudo apt install openssh-server

Pour en limiter l’accès, j’ai modifié le fichier /etc/deny.hosts du PC en y ajoutant la ligne suivante (l’adresse IP étant celle du NAS):

pascal@SH87R:~$ sshd: ALL EXCEPT 192.168.1.30

Et je redémarre le service sshd dans la foulée :

pascal@SH87R:~$ sudo systemctl restart sshd

Côté NAS, il faut maintenant générer la clef pour permettre le login automatique (taper Entrée pour toutes les questions) :

pascal@odroidhc2:~$ ssh-keygen

Puis on copie la clef sur le PC avec l’utilisateur rsync (l’adresse IP est cette fois celle du PC) :

pascal@odroidhc2:~$ ssh-copy-id -i /home/pascal/.ssh/id_rsa.pub rsync@192.168.1.20

Voilà, la commande rsync que l’on va utiliser dans le script pourra désormais se logguer sans avoir à saisir de mot de passe.

Script – deuxième partie

Retour au script donc, où il s’agit de copier le(s) fichier(s) images compressés vers le PC :

# Copie des images compressées vers le PC
rsync -a --delete "$backup_dir" rsync@192.168.1.20::omv-containers-rsync/

NOTES

  • il ne faut pas utiliser de « wildcards » comme le caractère « * » dans la commande rsync si l’on veut que l’option --delete fonctionne !
  • J’utilise cette option --delete afin d’effacer de la destination (sur le PC donc) les fichiers qui ne sont pas présents sur la source. L’idée est de ne garder qu’une seule version des containers, chaque nouvelle sauvegarde effacera la sauvegarde précédente. Il doit être possible d’améliorer le script pour établir un système plus sophistiqué de sauvegardes, mais pour l’instant cela me convient tel quel.
  • Pour la syntaxe de type rsync@adresse_IP::nom_module utilisée, voir l’article des sauvegardes.

Il ne reste plus qu’à faire le ménage sur le NAS, à savoir effacer le fichier archive (désormais copié sur le PC) mais aussi effacé l’image docker que l’on peut voir sur une commande docker images :

pascal@odroidhc2:~$ sudo docker images
REPOSITORY                           TAG       IMAGE ID       CREATED          SIZE
backup_nextcloud                     latest    73e18450d11a   4 seconds ago   331MB
linuxserver/nextcloud                latest    70e33dd606b8   3 months ago     330MB

On efface donc fichier et image docker en ajoutant ces lignes au script :

# Nettoyage des fichiers et images
docker rmi "$bck_nextcloud_imgname"
rm "$backup_dir"*.gz

Et voilà, notre script est prêt. Il ne reste plus qu’à l’ajouter au crontab du compte root, afin qu’il ait les droits d’exécuter les commandes docker. On exécute donc sudo crontab -e pour ajouter la tâche, et voici ce que ça donne pour une exécution tous les dimanches à 13h30 :

sudo crontab -l
# m h  dom mon dow   command
30 13 * * 0 /home/pascal/docker-container-backup.sh

Voilà ce que donne le script avec les trois containers nécessaires à Nextcloud (Nextcloud, Mariadb et Swag) :

cat docker-container-backup.sh 
#!/bin/bash
##########################################################
# Script de backup des containers Docker. 
##########################################################

# init des variables
backup_dir="/srv/dev-disk-by-label-DATA/Docker-Containers-Backup/"
now=$(date +%d-%m-%Y-%H-%M-%S)

nextcloud_imgname="linuxserver/nextcloud"
nextcloud_imgid=$(docker ps -a -f "ancestor=$nextcloud_imgname" -q -l)
bck_nextcloud_imgname=backup_nextcloud

swag_imgname="linuxserver/swag"
swag_imgid=$(docker ps -a -f "ancestor=$swag_imgname" -q -l)
bck_swag_imgname=backup_swag

mariadb_imgname="linuxserver/mariadb"
mariadb_imgid=$(docker ps -a -f "ancestor=$mariadb_imgname" -q -l)
bck_mariadb_imgname=backup_mariadb

# Création des images
docker commit -p "$nextcloud_imgid" "$bck_nextcloud_imgname"
docker commit -p "$swag_imgid" "$bck_swag_imgname"
docker commit -p "$mariadb_imgid" "$bck_mariadb_imgname"

# Sauvegarde des images sur le disque externe du NAS backup_dir
docker save -o  "$backup_dir""$bck_nextcloud_imgname"_"$now".tar "$bck_nextcloud_imgname"
docker save -o  "$backup_dir""$bck_swag_imgname"_"$now".tar "$bck_swag_imgname"
docker save -o  "$backup_dir""$bck_mariadb_imgname"_"$now".tar "$bck_mariadb_imgname"

# Compression des archives
gzip "$backup_dir"*.tar

# Copie des images compressées vers le PC
rsync -a --delete "$backup_dir" rsync@192.168.1.20::omv-containers-rsync/

# Nettoyage des images
docker rmi "$bck_nextcloud_imgname"
docker rmi "$bck_swag_imgname"
docker rmi "$bck_mariadb_imgname"

# Nettoyage des fichiers
rm "$backup_dir"*.gz

#Fin du script

Et voilà mes sauvegardes sur le PC :

Les sauvegardes des trois containers, au format gzip, compressées.

Je peux désormais dormir tranquille ! :ccol:

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *