Docker comme solution de virtualisation : les volumes

Source : Wikimédia. Image sous licence Apache 2.

Source : Wikimédia. Image sous licence Apache 2.

Suite de ma série d’articles sur Docker. Cette fois on délaisse la dockérisation de Sonerezh pour se concentrer sur les volumes.

Précédemment nous avons vu comment lier des containers entre eux pour les faire communiquer facilement. L’exemple étant de faire communiquer un container MariaDB avec un container Sonerezh. En effet, la philosophie de Docker nous dit qu’un conteneur égal une application ou un service. Hors de question alors d’embarquer MariaDB, Apache et Sonerezh dans le même conteneur.

Ces containers sont volatiles et doivent en tout cas être conçus pour l’être. Comment dès lors avoir de la persistance de données ? Comment être sûr que si mon container MariaDB qui contient la base de données de mon application ne va pas faire disparaître les données qu’il contient si par mégarde je l’arrête, ou si j’ai besoin de le supprimer ?

Tout cela, Docker le gère à travers ce qui s’appelle les volumes de données.

Qu’est-ce que les volumes de données Docker ?

C’est tout simplement un dossier un peu spécial qui outrepasse la couche UnionFS de nos containers et permet le partage de données entre un ou plusieurs containers, et la persistance de celles-ci. On trouve plusieurs autres fonctionnalités intéressantes :

  • Les volumes sont initialisés à la création du container. Si l’image de base contient des données au point de montage spécifié, celles-ci sont copiés dans le volume lors de son initialisation
  • Les volumes de données peuvent être partagés entre plusieurs containers (très pratique pour créer des clusters de container par exemple)
  • Les changements apportés aux données du volume sont pris en compte immédiatement
  • Les données restent sur votre hôte même si le container vient à disparaître

Ça peut sembler un peu flou au premier abord mais vous allez voir qu’avec un exemple ça va aller beaucoup mieux.

Ajouter un volume de données

La gestion des volumes se fait avec l’option -v (pour --volume) des commandes docker run ou docker create. Évidemment, plusieurs -v peuvent être placés les uns après les autres en fonction du nombre de volumes souhaités. Ajoutons un volume à l’image de MariaDB par exemple :

$ docker run --name mariadb-test --volume /var/lib/mysql -d mariadb

Ici le volume /var/lib/mysql a été créé dans mon container. Il est par défaut accessible en lecture / écriture mais il est possible de restreindre ces accès en utilisant /var/lib/mysql:ro pour read-only.

Où trouver ce volume sur mon hôte ?

Toujours grâce à la commande inspect :

$ docker inspect mariadb-test
[...]
"Mounts": [
        {
            "Name": "0afd0...68d73",
            "Source": "/var/lib/docker/volumes/0afd0...68d73/_data",
            "Destination": "/var/lib/mysql",
            "Driver": "local",
            "Mode": "",
            "RW": true
        }
    ],
[...]

Où « Source » indique le dossier sur l’hôte et « Destination » le point de montage dans le container. « RW » indiquant si le volume est accessible en lecture / écriture.

Mais il est vrai qu’il n’est pas évident de travailler avec des volumes à si bas niveau. Qui voudrait s’embêter à fouiller dans /var/lib/docker pour trouver le volume qu’il cherche. On peut faire plus simple : créer un autre conteneur qui va monter ce volume automatiquement. Ce deuxième conteneur pourrait être un service de sauvegarde de MySQL par exemple, qui monterait le volume, réaliserait sa sauvegarde et se terminerait.

$ docker run --volumes-from mariadb-test debian:latest monscriptdesauvegarde.sh

Notez que les volumes sont toujours conservés, que les containers soient arrêtés ou non. En revanche le volume (et les données) est supprimé une fois que le dernier container y faisant référence l’est aussi.

Pas mal non ?

Mouais pas mal. Mais dans le cas de Sonerezh, ma musique est dans /home/guillaume/Musique. Si je démarre un container Sonerezh avec un volume, il faudra que je copie toute ma musique dedans ?!

Non, c’est là que ça devient intéressant. Plutôt que de laisser Docker choisir l’emplacement du volume sur l’hôte, on peut spécifier un dossier en particulier. Dans le cas de Sonerezh, on va être capable d’indiquer à Docker de monter le dossier /home/guillaume/Musique de notre hôte sur le point de montage /music de notre container. L’application Sonerezh accédera donc à la musique via /music.

Et d’ailleurs ça se passe un peu comme les liaisons évoquées dans l’article précédent :

$ mkdir /home/guillaume/mariadb-volume
$ docker run --name mariadb-test --volume /home/guillaume/mariadb-volume:/var/lib/mysql -d -e MYSQL_ROOT_PASSWORD=pass mariadb
$ docker inspect mariadb-test
[...]
"Mounts": [
        {
            "Source": "/home/guillaume/mariadb-volume",
            "Destination": "/var/lib/mysql",
            "Mode": "",
            "RW": true
        }
    ],
[...]

Ici le dossier de ma /home est monté dans le container à /var/lib/mysql. D’ailleurs comme c’est ici que MySQL stocke toute ses données par défaut je devrais y trouver du contenu.

$ ls -l /home/guillaume/mariadb-volume
-rw-rw---- 1 999 docker  16K oct.  26 22:39 aria_log.00000001
-rw-rw---- 1 999 docker   52 oct.  26 22:39 aria_log_control
-rw-rw---- 1 999 docker  12M oct.  26 22:39 ibdata1
-rw-rw---- 1 999 docker  48M oct.  26 22:39 ib_logfile0
-rw-rw---- 1 999 docker  48M oct.  26 22:39 ib_logfile1
-rw-rw---- 1 999 docker    0 oct.  26 22:39 multi-master.info
drwx------ 2 999 root   4,0K oct.  26 22:39 mysql
drwx------ 2 999 docker 4,0K oct.  26 22:39 performance_schema

Tadaa !!!

C’est plus clair maintenant ? Je peux faire ce que je veux avec mes containers mariadb. Les arrêter, les supprimer, les mettre à jour… Tant que je continuerai de mapper /home/guillaume/mariadb-volume à /var/lib/mysql, mes données persisteront dans mes containers.

D’ailleurs à ce propos, si vous regardez la documentation de l’image Docker officielle de Sonerezh, vous voyez qu’il est conseillé de monter le volume /music, et de le faire correspondre à l’endroit où votre musique est stockée !

$ docker run --name sonerezh-app --link sonerezh-mariadb:mariadb \
                                 --volume /path/to/music:/music \
                                 --detach --publish 8080:80 \
                                 sonerezh/sonerezh:latest
Attention. Bien qu’en ligne, cette image n’est pas totalement stable et toujours en cours de développement. Je vous déconseille donc de l’utiliser hormis à des fins de test.

Les containers de volumes de données

Il peut aussi y avoir d’autres cas où nous avons besoin de partager un volume entre un ou plusieurs containers. Il est conseillé dans ce cas d’utiliser un container de volume de données (« data volume container« ).

Ce container de volume de données se créé avec la commande docker create. Restons avec MariaDB et créons un nouveau container de type volume de données.

$ docker create --volume /var/lib/mysql --name mariadb-data mariadb /bin/true

Bien que ce container n’exécute aucune application (le docker ps ne renvoie rien), on réutilise quand même l’image de mariadb car n’oubliez pas que les couches de filesystem sont partagées entre tous les containers utilisant la même image pour gagner de la place.

On peut maintenant réutiliser l’option --volumes-from pour monter /var/lib/mysql dans un autre container :

$ docker run --name mariadb-test --volumes-from mariadb-data  -d -e MYSQL_ROOT_PASSWORD=pass mariadb 

Et un deuxième :

$ docker run --name mariadb-test2 --volumes-from mariadb-data  -d -e MYSQL_ROOT_PASSWORD=pass mariadb

Les containers mariadb-test et mariadb-test2 accèdent tous les deux aux mêmes données puisqu’ils montent le même volume créé dans mariadb-data.

Sauvegarde, restauration et migration de volumes

L’avantage d’utiliser les containers de volume, c’est que nous pouvons facilement sauvegarde, exporter et restaurer nos données !

$ docker run --volumes-from mariadb-data -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /var/lib/mysql
Hein ?! Il se passe quoi là ?!
  • On crée un container qui va monter le volume présenté par mariadb-data que nous avions créé un peu plus tôt
  • L’option -v nous permet de lier le dossier /backup du container au dossier courant de notre hôte ($(pwd))
  • Ce container utilise l’image ubuntu
  • Et y exécute la commande tar cf /backup/backup.tar /var/lib/mysql

Comme /backup = $(pwd), l’archive se retrouve directement sur notre hôte !

$ ls -l *.tar
-rw-r--r-- 1 root root 119644160 nov.   1 12:45 backup.tar

Pour restaurer sur un autre hôte par exemple, il faut faire la procédure inverse :

# 1. On recrée le container de volume
$ docker create --volume /var/lib/mysql --name mariadb-data2 mariadb /bin/true
# 2. On y décompresse l'archive
$ docker run --volumes-from mariadb-data2 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar

Et le tour est joué !

Conclusion

Maintenant que vous savez tout des images, des containers, des liens et des volumes, vous pouvez commencer sérieusement à vous amuser sur Docker. Dans le prochain article, nous verrons comment automatiser la création de nouvelles images afin de gagner du temps. Nous verrons aussi comment partager nos images sur le Hub Docker afin d’en faire profiter toute la communauté.

D’ici là, amusez-vous bien 🙂

Cet article fait partie d’une suite :

  1. Docker comme solution de virtualisation : théorie
  2. Docker comme solution de virtualisation : installation
  3. Docker comme solution de virtualisation : les conteneurs
  4. Docker comme solution de virtualisation : les commits
  5. Docker comme solution de virtualisation : les liaisons

Cet article vous a plu ? Partagez-le sur les réseaux sociaux !

Twitter Facebook Google Plus email