Comme vous avez peut-être entendu la phrase une sauvegarde n'est pas bonne si elle n'est pas restaurable .
Il existe plusieurs façons de sauvegarder vos fichiers essentiels sur un serveur cloud. Mais ce qui est également important, c'est que vous ayez toujours une copie à jour de ces fichiers sur votre local systèmes.
Les sauvegarder sur le cloud est très bien. Mais une véritable sauvegarde n'est qu'une copie fraîche et régulièrement mise à jour qui est disponible de votre côté à tout moment. Pourquoi? Parce que ce sont VOS données !
Deux défis que je vais aborder à cet égard sont :
- La nécessité d'arrêter les conteneurs Docker sur un serveur de production pour éviter toute corruption de données (en particulier les bases de données) lors de la sauvegarde. Les fichiers sur les conteneurs de production en direct sont continuellement écrits.
- L'arrêt des conteneurs Docker entraîne également des temps d'arrêt, et vous ne pouvez pas vous le permettre, surtout si vous êtes en production.
Ces problèmes peuvent être résolus en utilisant des clusters au lieu de serveurs uniques. Mais ici, je me concentre sur des serveurs uniques et non sur des clusters pour maintenir les dépenses de service cloud aussi bas que possible.
Je n'arrêtais pas de me demander comment relever les deux défis ci-dessus. J'ai alors compris que nous pouvions utiliser à la fois une solution cloud et une solution localisée.
Par solutions basées sur le cloud, j'entends les services de sauvegarde fournis par les fournisseurs de services cloud tels que Linode, Digital Ocean et autres. Dans cette procédure pas à pas, je vais utiliser Linode.
Par solutions localisées, j'entends l'utilisation d'outils en ligne de commande ou basés sur une interface graphique pour télécharger la sauvegarde à partir de serveurs cloud sur votre système/bureau local. Ici, j'ai utilisé sftp (basé sur des commandes).
Tout d'abord, je vais expliquer comment effectuer la sauvegarde, puis comment la restaurer également.
Procédure de sauvegarde cloud + locale
Voyons d'abord la procédure de sauvegarde.
Activer les sauvegardes sur le serveur de production Linode (au cas où vous ne l'avez pas déjà fait)
Si vous utilisez un serveur de production sur Linode, il est fortement recommandé d'activer la sauvegarde de celui-ci lors de son premier déploiement. Un « nanode », comme on l'appelle, est livré avec 1 Go de RAM et propose le plan de sauvegarde suivant :

Toutes les autres solutions de sauvegarde offrent une fonctionnalité similaire mais à des taux plus élevés. Assurez-vous de l'avoir activé.
Prendre un instantané manuel comme sauvegarde sur le cloud
Entrez une date pour référence future. Ici, je l'appelle "manual-snapshot-11-05-21".

Dès que vous cliquez dessus, une confirmation vous est demandée :

Lorsque vous confirmez, vous trouverez une notification en bas à droite :

Vous pouvez surveiller la progression sur la même page, à côté de l'endroit où il est indiqué que votre serveur est en cours d'exécution (en haut à gauche) :

Une fois que c'est fait, vous remarquerez que la sauvegarde est la quatrième dans la liste.

Cloner le serveur de production
Bien que vous puissiez cloner directement un serveur (sur la base de sauvegardes planifiées antérieures) à partir du panneau de Linode, je vous recommande d'utiliser des sauvegardes manuelles comme indiqué à l'étape ci-dessus.
Ainsi, afin de procéder à la création d'un clone basé sur la sauvegarde manuelle la plus récente que vous avez effectuée, assurez-vous de suivre les instructions ci-dessous :
Allez dans le panneau Linode et cliquez sur "Créer":

Sélectionnez "Linode":

Sélectionnez l'onglet "Sauvegardes" :

Notez que l'instantané que vous prenez est basé sur un Linode de 2 Go. Sélectionnez l'instantané manuel que vous venez de créer :

Maintenant, assurez-vous de sélectionner la même spécification (Plan Linode 2 Go) pour votre clone :

Après avoir créé le nouveau serveur sur la base de la sauvegarde du serveur de production, vous disposerez d'un clone facilement disponible du serveur de production.
Connectez-vous au clone via ssh et arrêtez tous les conteneurs
Vous ne devriez avoir aucun problème pour vous connecter au nouveau clone via ssh car il utilise les mêmes clés publiques que le serveur de production. Il vous suffit d'utiliser la nouvelle adresse IP du clone. Je suppose que vous utilisez ssh seul et que l'authentification par mot de passe est désactivée, n'est-ce pas ? Lisez ce guide de sécurité ssh si vous ne l'avez pas encore fait.
Une fois connecté, arrêtez tous les conteneurs dont vous souhaitez sauvegarder les données. En règle générale, vous vous déplacez dans les répertoires d'application respectifs et utilisez la commande docker-compose down. Dans un environnement de production typique, on s'attend toujours à ce que vous utilisiez Docker Compose au lieu du classique docker stop
commande qui devrait être préférée lors des tests uniquement.
Par exemple, si j'avais Ghost en cours d'exécution avec son conteneur de base de données correspondant, je vérifierais d'abord ses informations respectives :
[email protected]:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6a3aafe12434 ghost:4.4.0 "docker-entrypoint.s…" 7 days ago Up 7 days 2368/tcp ghost_ghost_2
95c560c0dbc7 jrcs/letsencrypt-nginx-proxy-companion "/bin/bash /app/entr…" 6 weeks ago Up 10 days letsencrypt-proxy-companion
6679bd4596ba jwilder/nginx-proxy "/app/docker-entrypo…" 6 weeks ago Up 10 days 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp jwilder-nginx-proxy
1770dbb5ba32 mariadb:10.5.3 "docker-entrypoint.s…" 3 months ago Up 10 days ghost_db_1
Comme vous pouvez le voir ici, les noms des conteneurs sont ghost_ghost_2
et ghost_db_1
s'exécutant respectivement sous un proxy inverse. Arrêtons-les.
[email protected]:~$ cd ghost
[email protected]:~/ghost$ docker-compose down
Stopping ghost_ghost_2 ... done
Stopping ghost_db_1 ... done
Network net is external, skipping
[email protected]:~/ghost$
Si plusieurs applications s'exécutent derrière une configuration de proxy inverse nginx, utilisez la même procédure avec les noms de répertoire respectifs définis pour les applications. Arrêtez-les tous un par un.
Sauvegarder les volumes et les paramètres en tant qu'archives gzip
Voyons maintenant le processus de sauvegarde manuelle.
Sauvegarder les volumes nommés
Lorsque vous traitez avec des volumes Docker nommés, notez si les volumes ont été créés manuellement ou s'ils étaient basés sur une configuration Docker Compose générique dans laquelle l'application a été déployée pour la première fois.
Une configuration générique dans la section des volumes ressemble à :
volumes:
ghost:
ghostdb:
Le scénario ci-dessus est géré par Docker Compose, et les noms de volumes réels dont vous auriez besoin pour la sauvegarde seront ghost_ghost
et ghost_ghostdb
.
Dans le cas où les volumes ont été créés manuellement avec docker volume create volume-name
, la configuration ressemblerait à ce qui suit et serait strictement ghost
et ghostdb
seul :
volumes:
ghost:
external: true
ghostdb:
external: true
Néanmoins, vous devez les sauvegarder dans les deux cas, et vous devez également vérifier les chemins sur les conteneurs lorsque les volumes sont montés. Par exemple, sur une configuration Ghost typique avec MariaDB, les chemins peuvent être connus en consultant les sous-sections de volumes dans les définitions de service. Voici un extrait pour vous montrer ce que je veux dire :
ghostdb:
volumes:
- ghostdb:/var/lib/mysql
La configuration ci-dessus fait partie du service de base de données et de son conteneur correspondant qui serait créé une fois déployé.
De même, pour le service fantôme lui-même, le chemin est /var/lib/ghost/content
:
ghost:
volumes:
- ghost:/var/lib/ghost/content
Vous devez connaître ces chemins pour sauvegarder vos volumes.
Utilisez le docker volume ls
commande pour revérifier les noms de volumes présents sur le serveur cloné.
[email protected]:~/ghost$ docker volume ls
DRIVER VOLUME NAME
local ghost
local ghostdb
local nginx-with-ssl_acme
local nginx-with-ssl_certs
local nginx-with-ssl_dhparam
local nginx-with-ssl_html
local nginx-with-ssl_vhost
Ainsi, vous pouvez confirmer que les volumes sont bien ghost
et ghostdb
.
Il est temps de les sauvegarder ! Sur le clone de production, créons maintenant un répertoire de sauvegarde dans votre répertoire utilisateur :
mkdir ~/backup
Maintenant, je vais utiliser la commande suivante pour sauvegarder le contenu des volumes dans une archive tar :
docker run --rm -v ghostdb:/var/lib/mysql -v ~/backup:/backup ubuntu bash -c "cd /var/lib/mysql && tar cvzf /backup/ghostdb.tar.gz ."
Dans la commande ci-dessus, avec -v
ou --volume
, je monte le volume docker existant sur un nouveau conteneur Ubuntu et lie également le montage du répertoire de sauvegarde que je viens de créer. Plus tard, je me déplace dans le répertoire de la base de données à l'intérieur du conteneur et j'utilise tar pour archiver son contenu. --rm
est utilisé pour nettoyer automatiquement le conteneur et supprimer son système de fichiers lorsque le conteneur se ferme (car vous ne le souhaitez que tant que la tâche de sauvegarde ou de restauration est terminée).
Remarquez le point à la fin de la commande ci-dessus avant la fin des guillemets ("). Cela garantit que l'archive inclut ce qui se trouve à l'intérieur de /var/lib/ghost/content
seul et n'incluant pas le chemin d'accès complet lui-même en tant que sous-répertoires. Ce dernier causera des problèmes lors de la restauration de l'archive sur un nouveau volume sur un nouveau serveur. Alors, s'il vous plaît gardez cela à l'esprit.
Maintenant, j'ai une archive du volume de base de données MariaDB que notre blog Ghost utilise. De même, je dois également sauvegarder le volume fantôme :
docker run --rm -v ghost:/var/lib/ghost/content -v ~/backup:/backup ubuntu bash -c "cd /var/lib/ghost/content && tar cvzf /backup/ghost.tar.gz ."
N'oubliez pas que les commandes de sauvegarde ci-dessus sont basées sur des volumes externes initialement créés manuellement. Pour les volumes génériques créés et gérés par Docker Compose, les noms de volumes réels seraient plutôt ghost_ghost
et ghost_ghostdb
respectivement. Par exemple, pour ghost_ghostdb
, le ghost
le préfixe fait référence au nom du répertoire de votre application où vous avez vos fichiers de configuration Docker Compose et ghostdb
fait référence au nom de volume que vous avez défini dans votre configuration Docker Compose.
Paramètres de sauvegarde avec ou sans montages liés
Notez également que vous devez archiver le répertoire de composition du menu fixe fantôme, que vous utilisiez des montages liés ou des volumes nommés, car vos fichiers de configuration sont stockés ici.
Si vous utilisez des montages liés et des volumes Docker non nommés, l'intégralité du répertoire sera archivée, y compris les montages liés. Ici, je l'appelle ghost-docker-compose.tar.gz
pour éviter toute confusion :
[email protected]:~/ghost$ sudo tar cvzf ~/backup/ghost-docker-compose.tar.gz .
Les volumes montés liés n'ont pas besoin d'une section de volumes distincte dans un fichier Docker Compose. Ils aimeraient simplement ce qui suit lorsqu'il est défini dans le service :
ghost:
volumes:
- ./ghost:/var/lib/ghost/content
De même, le volume de base de données monté par liaison ressemblerait à :
ghostdb:
volumes:
- ./ghostdb:/var/lib/mysql
"./" indique le répertoire monté lié à l'intérieur du même répertoire fantôme dans lequel nous venons de "cd". Par conséquent, vous effectuez une sauvegarde complète de tous les fichiers dans ce cas (y compris les volumes et les fichiers de configuration).
La liaison de sauvegarde se monte comme des volumes nommés
Comme alternative, vous pouvez également sauvegarder individuellement les montages de liaison. Cela vous donne la possibilité de choisir si vous souhaitez que votre nouveau serveur ait une liaison montée ou une configuration de volume nommé sur Docker. La raison en est que les archives sont sauvegardées de la même manière que les volumes nommés décrits ci-dessus. Pour ce faire, vous devez "cd" dans les répertoires de l'application et de la base de données (montages liés) un par un.
cd ~/ghost/ghost
sudo tar cvzf ~/backup/ghost.tar.gz .
cd ~/ghost/ghostdb
sudo tar cvzf ~/backup/ghostdb.tar.gz .
Les montages liés et les volumes nommés ont leurs propres avantages et inconvénients. La question de savoir lequel d'entre eux est le plus idéal varie d'une application à l'autre. Par exemple, les développeurs Nextcloud suggèrent des volumes nommés, tandis que les développeurs Rocket.Chat suggèrent des montages liés.
Passant à autre chose, il est temps que vous récupériez ces archives de votre côté.
Télécharger les archives sur votre système local en utilisant sftp
En utilisant sftp, vous pouvez immédiatement télécharger vos archives sur votre système local. Ici, j'utilise le port 4480 et l'IP 12.3.1.4 comme exemple. Il fait référence au même port utilisé par ssh.
[email protected]:~$ sftp -oPort=4480 [email protected]
Connected to 12.3.1.4.
sftp> get /home/avimanyu/backup/ghost.tar.gz /home/user/Downloads
Fetching /home/avimanyu/backup/ghost.tar.gz to /home/user/Downloads/ghost.tar.gz
/home/avimanyu/backup/ghost.tar.gz 100% 233MB 6.9MB/s 00:34
sftp> get /home/avimanyu/backup/ghostdb.tar.gz /home/user/Downloads
Fetching /home/avimanyu/backup/ghostdb.tar.gz to /home/user/Downloads/ghostdb.tar.gz
/home/avimanyu/backup/ghostdb.tar.gz 100% 26MB 6.5MB/s 00:03
sftp> get /home/avimanyu/backup/ghost-docker-compose.tar.gz /home/user/Downloads
Fetching /home/avimanyu/backup/ghost-docker-compose.tar.gz to /home/user/Downloads/ghost-docker-compose.tar.gz
/home/avimanyu/backup/ghost-docker-compose.tar.gz 100% 880 6.0KB/s 00:00
sftp> exit
[email protected]:~$
Comme vous pouvez le voir ici, le get
commande sur sftp est bien plus rapide que rsync ou scp . Une fois le téléchargement est terminé, vous verrez l'invite sftp où vous pouvez entrer exit
et sortez de la console sftp. Les fichiers téléchargés seraient disponibles sur /home/user/Downloads
.
À ce stade, vous pouvez dire que vous avez effectué une sauvegarde complète de votre application docker.
Mais comme je dois le répéter, ce n'est pas bon si vous ne pouvez pas le restaurer.
Procédure de restauration
Maintenant que vous savez comment faire une sauvegarde, il est temps de voir comment restaurer à partir d'une sauvegarde.
Créer un nouveau serveur sur le cloud
Créez un nouveau serveur à partir de votre tableau de bord de service Cloud. J'en ai parlé dans notre section de sauvegarde. Sur Linode, cela ressemble à :

Il est recommandé de conserver les mêmes spécifications de serveur que celles du serveur d'origine à partir duquel les archives ont été sauvegardées (mentionné précédemment).
Télécharger les archives de sauvegarde sur le nouveau serveur
En supposant que vous puissiez maintenant vous connecter au nouveau serveur en fonction de vos paramètres ssh enregistrés sur votre fournisseur de services cloud, téléchargez les fichiers sur le serveur avec le put
de sftp commande :
[email protected]:~$ sftp -oPort=4480 [email protected]
Connected to 12.3.1.5.
sftp> put /home/user/Downloads/ghostdb.tar.gz /home/avimanyu
Uploading /home/user/Downloads/ghostdb.tar.gz to /home/avimanyu/ghostdb.tar.gz
/home/iborg/Downloads/ghostdb.tar.gz 100% 26MB 6.2MB/s 00:04
sftp> put /home/user/Downloads/ghost.tar.gz /home/avimanyu
Uploading /home/user/Downloads/ghost.tar.gz to /home/avimanyu/ghost.tar.gz
/home/iborg/Downloads/ghost.tar.gz 100% 233MB 7.2MB/s 00:32
sftp> put /home/user/Downloads/ghost-docker-compose.tar.gz /home/avimanyu
Uploading /home/user/Downloads/ghost-docker-compose.tar.gz to /home/avimanyu/ghost-docker-compose.tar.gz
/home/iborg/Downloads/ghost-docker-compose.tar.gz 100% 880 22.6KB/s 00:00
sftp> exit
[email protected]:~$
Si vous préférez utiliser une interface graphique pour le téléchargement, vous pouvez toujours utiliser FileZilla.
Restaurer les paramètres et les volumes
Tout d'abord, restaurez le répertoire docker compose de votre configuration Ghost.
mkdir ghost
cd ghost
sudo tar xvf ~/backup/ghost-docker-compose.tar.gz
Comme alternative, vous pouvez également essayer de restaurer la propriété de l'utilisateur (les autorisations sont déjà préservées) qui pourraient être utiles lors de la restauration des répertoires montés liés (déjà présents dans les archives), avec --same-owner
:
sudo tar --same-owner -xvf ~/backup/ghost-docker-compose.tar.gz
Si vous souhaitez vous fier à Docker Compose pour gérer les nouveaux volumes, créez-les d'abord. Conformément à notre discussion dans la section des volumes de sauvegarde ci-dessus, vous devrez évidemment suivre les conventions de dénomination nécessaires :
docker volume create ghost_ghost
docker volume create ghost_ghostdb
Si vous souhaitez les définir comme externes dans votre configuration Docker Compose, les noms doivent être différents (révisez les deux commandes ci-dessus) :
docker volume create ghost
docker volume create ghostdb
Pour restaurer le volume MariaDB pour Ghost :
docker run --rm -v ghostdb:/restore -v ~/backup:/backup ubuntu bash -c "cd /restore && tar xvf /backup/ghostdb.tar.gz"
Pour restaurer le volume Ghost lui-même :
docker run --rm -v ghost:/restore -v ~/backup:/backup ubuntu bash -c "cd /restore && tar xvf /backup/ghost.tar.gz"
Assurez-vous que les paramètres DNS sont restaurés en fonction de la nouvelle adresse IP
Puisque vous utilisez un nouveau serveur, l'adresse IP a définitivement changé et doit donc être révisée pour votre domaine. Vous pouvez vérifier ces prérequis du docker proxy inverse nginx comme référence là où cela a été discuté.
Lancer de nouveaux conteneurs avec les paramètres nécessaires et les volumes restaurés
Relancez maintenant la configuration sur le nouveau serveur :
docker-compose up -d
Si vous suivez assidûment toutes les instructions ci-dessus, vous aurez maintenant une application Web Docker entièrement restaurée basée sur votre sauvegarde.
Détruire le clone
Une fois que vous êtes assuré que votre objectif est atteint, il n'est plus nécessaire d'avoir le clone, sauf si vous souhaitez le conserver pour les tests. Donc, si vous n'en voulez plus, veuillez supprimer le Linode (DOUBLE CHECK !):

Réflexions finales
Il existe déjà de nombreuses solutions utilisant de tels procédés en parties et portions. Mais cela demande des temps d'arrêt car les conteneurs doivent être arrêtés. Ce défi est relevé en utilisant des sauvegardes cloud à partir de clones de production et non des serveurs de production eux-mêmes.
Au lieu d'utiliser un serveur supplémentaire 24h/24 et 7j/7 comme cluster pour des sauvegardes sans temps d'arrêt, nous n'en utilisons que momentanément un pour garantir la même chose. Cela permet de meilleurs FinOps.
Si vous préférez utiliser une interface graphique pour télécharger ou charger vos sauvegardes, vous pouvez utiliser sftp
via FileZilla.
Étant donné que vous sauvegardez les fichiers sur un serveur cloné et non sur le serveur de production lui-même, vous économisez un temps de disponibilité précieux, en plus d'éviter les contretemps inattendus que vous pourriez rencontrer au cours du processus. Pour être honnête, vous pouvez être libre de tout souci et jouer avec sans aucune tension car vous ne touchez pas au serveur de production;)
Je ne peux pas nier que l'ensemble du processus est assez complet, mais il prend certainement soin de notre objectif. Au-delà, cette procédure pourrait également être complètement automatisée à l'avenir, avec une synchronisation minutieuse entre le cloud et votre système local.
Si vous avez d'autres suggestions sur la sauvegarde et la restauration Docker sans temps d'arrêt, veuillez partager vos réflexions dans la section ci-dessous. Tout autre commentaire ou commentaire est le bienvenu.