Afin de pouvoir suivre cette bonne pratique, il est indispensable en amont de la création d’un conteneur de décider quelle donnée localiser sur un volume pour la sauvegarder à le recréation du-dit conteneur. Trois options s’offrent alors à nous.
- Utiliser un bind mount depuis l’hôte
- Créer un volume Docker
- Générer une partition tmpfs pour des données non-persistantes
Dans les deux premiers cas, il est possible de monter un même volume dans plusieurs conteneurs, par exemple pour leur offrir un espace d’écriture commun.
Utiliser un bind mount
Il s’agissait de la toute première option disponible. J’ai fait mes armes avec celle-ci et c’est l’option que je continue d’utiliser le plus.
Pour utiliser un bind mount, il faut, à la création d’un conteneur, spécifier un dossier ou fichier avec un chemin absolu après l’option -v
, ou utiliser --mount
avec un type=bind.
# Cas d'un fichier avec -v
docker run -v /etc/hostname:/etc/hostname bash cat /etc/hostname
# Cas d'un dossier avec -v
docker run -v /srv/telegraf:/srv/telegraf bash find /srv/telegraf
# Cas d'un fichier avec --mount
docker run --mount type=bind,src=/etc/hostname,dst=/etc/hostname bash cat /etc/hostname
# Cas d'un dossier avec --mount
docker run --mount type=bind,src=/srv/telegraf,dst=/srv/telegraf bash find /srv/telegraf
À noter que si la destination est un dossier ou fichier déjà existant, la source se substituera à la destination, de la même manière qu’une partition montée sur un chemin (dossier) existant d’un système Linux ne l’écrasera pas mais le rendra inaccessible.
Utiliser un volume nommé
Un volume nommé est géré entièrement par Docker, quel que soit le système (Linux ou Windows par exemple), c’est donc la solution à privilégier dans le cas de système hétérogènes. Un volume nommé sera créé à la demande si son nom (la source, ou ‘src’) n’existe pas, et sera réutilisé s’il existe.
# Cas d'un dossier avec -v
docker run -v telegraf-conf:/srv/telegraf telegraf
# Cas d'un dossier avec --mount
docker run --mount type=volume,src=telegraf-conf,dst=/srv/telegraf telegraf
Une fois créé, un volume nommé ne sera nettoyé que par une action d’un administrateur, attention à la surutilisation de l’espace !
Dans les coulisses, le volume est tout simplement un dossier, par défaut sous Linux stocké dans /var/lib/docker/volumes. Comme il s’agit d’un objet géré par l’API Docker, plusieurs commandes sont alors accessibles pour la gestion de ces volumes nommés :
docker volume ls → Lister les volumes
docker volume create → Créer manuellement un volume (simple dossier vide)
docker volume rm → Supprimer un volume s'il n'est utilisé par aucun conteneur existant
docker volume prune → Nettoyer les volumes non utilisés
Générer un espace tmpfs
Seulement disponible sur Linux, cette option permet créer un espace de travail temporaire en mémoire, qui sera donc perdu à l’arrêt du conteneur. Les performances sont alors maximales en sacrifiant toute résilience des données.
Deux façons de créer un tmpfs, utiliser --tmpfs ou --mount. Encore une fois, --mount est plus flexible avec des options de configuration, qui n’existent tout simplement pas avec --tmpfs.
# Cas avec --tmpfs, où on créé un fichier random dans l'espace tmpfs monté
sudo docker run --tmpfs /tmp bash -- dd if=/dev/zero of=/tmp/test bs=1000 count=10000
# Cas avec --mount où on limite la taille et les droits de l'espace partagé en mémoire
sudo docker run --mount type=tmpfs,dst=/tmp/,tmpfs-size=50M,tmpfs-mode=0770 bash
Différences entre -v et –mount
Ces deux options peuvent permettre le même résultat. La version --mount est plus récente, et conseillée pour les débutants car elle ne laisse moins la place aux erreurs.
La syntaxe de -v est plus courte et plus légère :
# Dans le cas d'un bind mount
-v <dossier_hôte>:<dossier_conteneur>[:ro]
# Dans le cas d'un volume nommé
-v <volume_nommé>:<dossier_conteneur>[:ro]
Alors que la syntaxe de –mount est plus complète :
--mount type=bind,src=<source>,dst=<destination>,readonly
--mount type=volume,src=<source>,dst=<destination>
--mount type=tmpfs,dst=<destination>
Avec l’utilisation de bind-mounts, la différence est majeure dans le cas où le volume source n’existe pas :
- Avec -v, le dossier source est créé s’il n’existe pas. La destination dans le conteneur est également créée, sous forme de dossier systématiquement.
- Avec --mount, une erreur sera renvoyée si le dossier source n’existe pas On peut donc estimer que l’option --mount est plus propre car ne permettra pas de laisser démarrer un conteneur si typo il y a eu dans la spécification de son bind mount côté hôte.