Sauvegarder/Restaurer la base de données de Parse Server sur Digital Ocean Spaces

Dans l'article précédent nous avons vu comment mettre en place un environnement Parse Server, le but aujourd'hui est de venir rajouter un service de sauvegarde automatique de la base de données pour l'environnement de production.

La sauvegarde de notre base de données sera stockée sur Digital Ocean Spaces.

Spaces est un service de stockage d'objet, c'est un peu le pendant d'Amazon S3 mais chez Digital Ocean. Ce qui est intéressant c'est qu'il utilise le meme fonctionnement qu'Amazon S3 ce qui signifie que beaucoup de librairie permettant de manipuler S3 fonctionneront avec Spaces. Si vous souhaitez tester Spaces ainsi que les autres services de Digital Ocean utilisez ce lien pour vous inscrire et vous bénéficierez de 10 $ de crédits.

Cet article traite de la sauvegarde de la base de données de Parse Server dans notre cas il s'agit d'une base MongoDB le système qui sera mis en place peut s'appliquer à n'importe quel environnement utilsisant une base de données MongoDB

Fonctionnement

Pour mettre en place ce système nous allons nous servir des librairies et services suivants :

  • Docker : nous allons créer un container qui aura pour seul objectif de lancer les sauvegardes.
  • Boto3 : Sdk python pour Amazon web service qui nous permettra de pousser les sauvegardes sur Spaces.
  • Cron : Pour planifier le démarrage de notre sauvegarde.
  • MongoDump / MongoRestore : Pour générer/restaurer le backup de notre base de données.

Dans un premier temps nous allons créer deux scripts python. Ces deux scripts utiliseront boto3 pour interagir avec Spaces. L'un permet d'uploader le backup pour la sauvegarde et l'autre permettra de télécharger le backup dans le cas ou l'on souhaite restaurer les données.

Ensuite nous aurons deux scripts shell un pour la sauvegarde et un pour la restauration.

Pour la sauvegarde le script va se connecter à notre base de données MongoDB et utilisé mongodump pour extraire les données de la base une fois les données extraites et compressées ce script exécutera notre script python pour uploader le fichier.

Pour la restauration le script exécutera dans un premier temps le script python pour télécharger la sauvegarde et ensuite une fois la sauvegarde récupérée il utilisera mongorestore pour restaurer les données.

Le script de sauvegarde sera lancé automatiquement par Cron tandis que le script de restauration sera lancer à la main si besoin.

Mise en place du projet

Nous allons partir de la configuration du serveur Parse de l'article précédent. Vous pouvez télécharger cette configuration ici.

Une fois les sources récupérées, nous allons créer un dossier qui contiendra l'ensemble des scripts et le Dockerfile à la racine du projet.

mkdir cron && cd cron

Création des scripts python

Maintenant nous allons créer nos scripts python qui serviront pour l'upload et le download des sauvegardes.

Upload de la sauvegarde

Créer un dossier scripts et ajoutez-y le fichier backup.py

import boto3
import os
import datetime

session = boto3.session.Session()
client = session.client('s3',
                        region_name= os.environ['SPACE_REGION'],
                        endpoint_url=os.environ['SPACE_URL'] ,
                        aws_access_key_id= os.environ['SPACE_ACCESS_KEY'],
                        aws_secret_access_key= os.environ['SPACE_ACCESS_SECRET'])

client.upload_file('/home/backups/tmp_dump.gz',
                   os.environ['SPACE_NAME'],
                   datetime.datetime.today().strftime("%Y-%m-%d-%H:%M:%S")+".gz")
  1. On importe les librairies nécéssaires.
  2. On déclare un client avec les variables d'environnement contenant les informations de notre Spaces.
  3. On upload le fichier sur Spaces.

Le fichier de sauvegarde est nommé tmp_dump.gz car il sera automatiquement supprimé une fois l'upload terminé par contre dans notre Spaces le fichier aura pour nom la date et l'heure ou il a été upload.

Download de la sauvegarde

Toujours dans le dossier scripts ajoutez le fichier download.py

import boto3
import os
import datetime
import sys

session = boto3.session.Session()
client = session.client('s3',
                        region_name= os.environ['SPACE_REGION'],
                        endpoint_url=os.environ['SPACE_URL'] ,
                        aws_access_key_id= os.environ['SPACE_ACCESS_KEY'],
                        aws_secret_access_key= os.environ['SPACE_ACCESS_SECRET'])

client.download_file(os.environ['SPACE_NAME'],  sys.argv[1], '/home/backups/'+sys.argv[1])
  1. On importe les librairies nécéssaires.
  2. On déclare un client avec les variables d'environnement contenant les informations de notre Spaces.
  3. On télécharge le fichier.

Pour le téléchargement on utilise le code suivant sys.argv[1] ce code représente le nom du fichier que l'on souhaite télécharger et qui est placé à la fin de la commande lancée pour la restauration.

Exemple :

python download.py 2018-07-06-01:00:02.gz

Nos scripts python sont maintenant prêts cependant comme vous l'aurez remarqué ces derniers ne s'occupent que de l'upload et du download des sauvegardes. Pour générer / restaurer la sauvegarde nous allons avoir besoin des scripts shell qui vont s'occuper de ça pour nous.

Création des scripts shell

Script de sauvegarde

On commence par le script de backup toujours dans le scripts ajouter le fichier backup_mongo.sh avec le code suivant :

#!/bin/bash

set -e

DB=$DB_DATABASE
USER=$DB_USERNAME
PWD=$DB_PASSWORD
PORT=$DB_PORT
NAME=tmp_dump.gz

echo "=============================="
echo "Sauvegarde de la base sur le Space DigitalOcean: $SPACE_NAME"
echo "=============================="
echo ""
echo "=============================="
echo "Création de l'archive contenant les données de la base MONGODB : $DB"
echo "=============================="
echo ""

mongodump  --db $DB --username $USER --password $PWD --host mongo:$PORT --archive=/home/backups/$NAME --gzip

echo "=============================="
echo "Copie de l'archive sur le Space DigitalOcean : $SPACE_NAME"
echo "=============================="
echo ""

python /home/scripts/backup.py

echo "=============================="
echo "Suppréssion de l'archive local"
echo "=============================="
echo ""

rm /home/backups/$NAME

echo "=============================="
echo 'Sauvegarde terminé !'
echo "=============================="
  1. On récupère les variables d'environnement.
  2. On utilise mongodump pour générer une archive qui contient les données de la base de données.
  3. On lance le script python qui permet de copier l'archive sur Digital Ocean.
  4. Enfin on supprime l'archive temporaire de notre système.

Script de restauration

Maintenant nous allons créer le script qui nous permet de restaurer les données en cas de problème :

Créez le fichier restore_mongo.sh

#!/bin/bash

set -e

DB=$DB_DATABASE
USER=$DB_USERNAME
PWD=$DB_PASSWORD
PORT=$DB_PORT
NAME=$1

echo "=============================="
echo "Téléchargement de l'archie depuis le Space DigitalOcean : $SPACE_NAME"
echo "=============================="
echo ""

python /home/scripts/download.py $NAME

echo "=============================="
echo "Restauration des données dans la base MongoDB $DB "
echo "=============================="
echo ""

mongorestore --db $DB --username $USER --password $PWD --host mongo:$PORT --drop --gzip --archive=/home/backups/$NAME


echo "=============================="
echo 'Restauration terminée'
echo "=============================="
  1. On récupère les variables d'environnement.
  2. On lance le script de téléchargement de l'archive.
  3. On utilise mongorestore pour restaurer les données dans notre base.

Comme pour le script python avec sys.argv[1] on récupérer le nom du fichier l'aide $1 .

Donc pour restaurer les données vous devez lancer la commande suivante depuis le dossier script votre container :

restore_mongo.sh 2018-07-06-01:00:02.gz

Création de la tâche Cron

Nos scripts sont prêts, nous voulons donc automatiser la sauvegarde afin que celle-ci soit faite tous les jours à 01H00. Pour ce faire nous allons créer un fichier crontab à la racine du dossier cron et ajouter le code suivant :

 0 1 * * * root . /root/project_env.sh; /home/scripts/backup_mongo.sh >> /var/log/cron.log 2>&1
# Don't remove the empty line at the end of this file. It is required to run the cron job
  1. On définit la récurence de la tâche avec 0 1 * * * (tous les jours à 01H00). Si vous voulez en savoir plus sur les différentes possibilités de planification cliquez-ici.
  2. On indique que l'on souhaite lancer le script avec l'utilisateur root.
  3. On précise ou se trouve les variables d'environnement.
  4. On indique le script à lancer.

Pour le point 3 cron ne sait pas dans quel environnement il est lancé c'est pour ça qu'on lui précise quelles variables d'environnement utiliser : /root/project_env.sh;

Cependant tous l'intérêt des variables d'environnement est de ne les préciser qu'au lancement de notre container et ne pas avoir à les écrire ailleur.

Nous allons voir dans la création du Dockerfile comment générer le fichier project_env.sh automatiquement au lancement du container avec les bonnes variables d'environnement.

Création du Dockerfile

Nous arrivons bientôt à la fin de la configuration il nous reste à créer le Dockerfile à la racine de notre dossier cron :

FROM ubuntu:16.04

USER root
# Installation python cron et boto3
RUN \
  apt-get update && \
  apt-get install -y python python-dev python-pip python-virtualenv cron apt-transport-https  && \
  rm -rf /var/lib/apt/lists/* && pip install boto3
# Installation de mongodump et mongorestore
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 && \
  echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list && \
  apt-get update && apt-get install -y mongodb-org-tools
# Ajout des scripts et la tâche cron
COPY crontab /etc/cron.d/backup-cron
COPY scripts /home/scripts/
RUN mkdir /home/backups/
# Creation du fichier de log
RUN touch /var/log/cron.log
# Attribution des droits d'éxécution
RUN chmod 0644 /etc/cron.d/backup-cron
RUN ["chmod", "+x", "/home/scripts/backup_mongo.sh"]
RUN ["chmod", "+x", "/home/scripts/restore_mongo.sh"]


# Démarrage du service
CMD printenv | sed 's/^\(.*\)$/export \1/g' > /root/project_env.sh && cron && tail -f /var/log/cron.log

Comme nous l'avons vu précédemment il faut créer le fichier project_env.sh pour que cron puisque avoir accès au variables d'environnement. C'est la commande suivante qui est en charge de faire ce travail :

printenv | sed 's/^\(.*\)$/export \1/g' > /root/project_env.sh

Configuration docker-compose

Maintenant que notre service de sauvegarde/restauration est prêt nous allons l'ajouter à la configuration docker-compose de notre serveur Parse.

Dans le fichier docker-compose.yml du serveur Parse rajoutez le code suivant à la suite des services précédents :

cron:
  build: ./cron/
  container_name: 'dwa-studio-cron-backup'
  image: dwa-studio/parse-server
  environment:
    SPACE_REGION: 'region'
    SPACE_URL: 'url_spaces'
    SPACE_ACCESS_KEY: 'access_key'
    SPACE_ACCESS_SECRET: 'access_secret'
    SPACE_NAME: 'space_name'
    DB_USERNAME: 'user'
    DB_PASSWORD: 'MONGODB_PASSWORD'
    DB_DATABASE: 'db_name'
    DB_PORT: 27017
  volumes:
    - ./cron/scripts:/home/scripts
    - ./cron/backup:/home/backups
  depends_on:
    - mongo

Il ne manque plus qu'à ajouter les informations de votre Spaces et faire en sorte que les variables d'environnement concernant l'accès à votre base mongodb soit les même que celles de la configuration du service mongodb.

mongo:
  image: 'bitnami/mongodb:latest'
  container_name: 'dwa-studio-mongo-db'
  restart: always
  ports:
    - '27017:27017'
  environment:
    MONGODB_ROOT_PASSWORD: 'MONGODB_ROOT_PASSWORD'
    MONGODB_USERNAME: 'user'
    MONGODB_PASSWORD: 'MONGODB_PASSWORD'
    MONGODB_DATABASE: 'db_name'
  volumes:
    - ./mongo:/bitnami

Exemple de configuration :

Imaginons que j'ai créé un Spaces nommée test-backup dans la région Amsterdam 3 sur Digital Ocean alors voici les valeurs des variables d'environnement concernant le Spaces :

SPACE_REGION: 'ams3'
SPACE_URL: 'https://ams3.digitaloceanspaces.com'
SPACE_ACCESS_KEY: 'ACCESS_KEY_GENERE'
SPACE_ACCESS_SECRET: 'ACCESS_SECRET_GENERE'
SPACE_NAME: 'test-backup'

Utilisation

Une fois que vous aurez lancé les services avec la commande :

docker-compose up

Les backup se feront automatiquement grâce à la tâche cron. Cependant si vous souhaiter tester manuellement l'upload pour valider votre configuration ou bien que vous souhaitez restaurer vos données voici les étapes à suivres :

1- Récuper l'id du container cron :

docker ps

2- Une fois que vous avez copier l'id du container executez la commande suivante :

 docker exec -it [REMPLACER PAR L'ID DU CONTAINER]  bin/bash

3- Une fois que vous êtes dans le container :

Pour générer le backup :

home/scrips/backup_mongo.sh

Pour récuperer le backup :

home/scrips/restore_mongo.sh [NOM DU FICHIER DE BACKUP]

Voila maintenant vous pouvez mettre en place le système de sauvegarde de vos données sur votre serveur simplement.

Partagez cet article si vous le souhaitez et si vous avez des questions vous pouvez me contacter par le chat.