Gestion de volumes sous Docker
Posted on lun. 21 janvier 2019 in Devops
Quelques commandes utiles
Obtenir des informations sur les volumes associés à un conteneur :
docker container inspect -f "{{ json .Mounts }}" <container_name> | python -m json.tool
Cette commande permet notamment de vérifier l'emplacement et le nom du volume sur le disque de l'hôte.
L'option -f
(abbréviation de --format
) permet de filtrer les résultats en fonction d'un ou plusieurs critères exprimés sous forme de Go template. Le "." correspond à l'object courant et dans l'exemple il s'agit de la valeur de la propriété Mounts
.
json
est une fonction fournie par Docker pour encoder les chaînes de caractères à ce format.
Notons enfin le pipe de présentation final : python -m json.tool
json.tool
est un module Python utilisé en ligne de commande pour l'affichage indenté des objets JSON.
Mise en pratique pour un conteneur "postgres" (basé sur une image officielle postgresql) :
docker container inspect -f "{{ json .Mounts }}" postgres | python -m json.tool
[
{
"Destination": "/var/lib/postgresql/data",
"Driver": "local",
"Mode": "",
"Name": "5452bbee2344cbcdb9768f3451a7e8c797c6f77dae57389bf870e92f3175725e",
"Propagation": "",
"RW": true,
"Source": "/var/lib/docker/volumes/5452bbee2344cbcdb9768f3451a7e8c797c6f77dae57389bf870e92f3175725e/_data",
"Type": "volume"
}
]
Destination
correspond au point de montage dans le conteneur. Name
et Source
correspondent respectivement au nom et à l'emplacement du volume sur le disque de l'hôte.
Identifier le conteneur auquel est rattaché un volume :
docker ps -a --filter volume=<volume_name_or_id>
C'est un peu l'inverse de la commande précédente. Partant du nom d'un volume local, retrouver à quel conteneur il est rattaché.
Exemple :
docker ps -a --filter volume=5452bbee2344cbcdb9768f3451a7e8c797c6f77dae57389bf870e92f3175725e
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
81306660f9b1 postgres:9.4 "docker-entrypoint.s…" 3 days ago Exited (255) 15 hours ago 5432/tcp postgres
Supprimer les volumes inutilisés
Rappelons tout d'abord qu'un conteneur stoppé n'est pas automatiquement supprimé à moins de l'avoir démarré avec l'option --rm
.
Cf. https://docs.docker.com/config/pruning/
Les volumes, quant à eux, ne sont jamais supprimés de manière automatique. La commande suivante permet de supprimer tous les volumes non utilisés (ceux auxquels aucun conteneur n'est rattaché) :
docker volume prune
Cela évite d'avoir à supprimer les volumes un par un en les identifiant par leurs noms, en utilisant une commande du type : docker volume rm <volume_id>
Exemples de backup/restauration
Ces exemples sont très largement inspirés de la page d'aide de Docker sur les volumes :
https://docs.docker.com/storage/volumes/
Créer un volume dbdata à la racine d'un conteneur nommé "dbstore"
docker run -ti -v /dbdata --name dbstore debian:8-slim /bin/bash
L'image utilisée ici est une debian:8-slim
.
Pour l'exemple, créons 2 fichiers dans le répertoire /dbdata
du conteneur :
root@d3b8c5120cca:/# for i in {1,2}; do echo "Content of file$i" > file$i.log; done;
Puis stoppons le conteneur :
root@d3b8c5120cca:/# exit
Backup
docker run --rm --volumes-from dbstore -v $(pwd):/backup alpine sh -c "cd /dbdata/ && tar -zcvf /backup/backup.tgz *"
Disséquons la commande :
-
Lancer un conteneur temporaire (à partir d'une image alpine) en montant le(s) volume(s) du conteneur nommé
dbstore
:
docker run --rm --volumes-from dbstore ... alpine
-
Lier le répertoire courant sur l'hôte au point de montage
/backup
du conteneur temporaire :
-v $(pwd):/backup
-
Compresser le contenu du répertoire
/dbdata
dans un fichier gzip, identifié par son chemin absolu/backup/backup.tgz
:
sh -c "cd /dbdata/ && tar -zcvf /backup/backup.tgz *"
Suppression des fichiers d'origine
Redémarrons le conteneur dbstore :
docker container start -ai dbstore
Supprimons les fichiers précédemment créés afin de simuler une erreur involontaire :
cd /dbdata && rm file*
Stoppons le conteneur :
exit
Restauration
Les deux premières étapes sont les mêmes.
La troisième permet de se déplacer dans le point de montage /dbdata
et de décompresser le fichier backup.tgz
:
docker run --rm --volumes-from dbstore -v $(pwd):/backup alpine sh -c "cd /dbdata && tar zxvf /backup/backup.tgz"
Vérifions maintenant si la restauration a bien fonctionné :
docker container start -ai dbstore
root@d3b8c5120cca:/# ls -l /dbdata
total 0
-rw-r--r-- 1 root root 0 Feb 3 08:17 file1.log
-rw-r--r-- 1 root root 0 Feb 3 08:17 file2.log
root@d3b8c5120cca:/# cat file*.log
Content of file1
Content of file2
Conclusion
Docker offre beaucoup de souplesse dans le partage de contenus entre hôte et conteneurs. Les exemples présentés ci-dessus en sont une illustration partielle et témoignent de la facilité avec laquelle on peut utiliser des données persistentes au sein de cet environnement.
Pour en savoir plus :