Les volumes dans Docker

Les volumes dans Docker

Table des matières

Il y a bien un truc qui peu déstabiliser quand on débute avec Docker, c'est les volumes. Personnellement ça m'a un peu gonflé quand j'ai commencé. 😅
C'est pourquoi je me suis dit qu'on pourrait en discuter de la manière la plus simple et compréhensible possible.

Si cela vous tente, on va démêler tout ça! Il y a des variantes qui ne seront pas expliquées car le principe c'est vraiment de comprendre un minimum les volumes sans s'embrouiller. Enfin, j'espère.

Rappel sur l'utilité et la raison d'être des volumes : assurer la persistance des données stockées.

Il faut se dire qu'il y a deux façons d'assurer la persistance de vos données, autrement dit de créer des dossiers qui vont contenir vos données:

  • les volumes docker
  • les bind mounts

Voici, sous forme de tableau les principales différences. Nous verrons plus loin comment ça se présente dans un docker-compose.

Docker VolumesBind Mounts
Les volumes Docker sont gérés par Docker et sont généralement stockés dans un répertoire spécifique sur la machine hôte.Les bind mounts font référence à un répertoire sur la machine hôte. Le répertoire est directement monté dans le conteneur à un chemin spécifié.
Les volumes sont indépendants du cycle de vie du conteneur et peuvent être créés, gérés et partagés sur plusieurs conteneurs.Les bind mounts sont étroitement couplés au système de fichiers hôte et n'ont pas les mêmes fonctionnalités et flexibilité que les volumes Docker.
Les volumes offrent plus de fonctionnalités, telles que les commandes de gestion des données et l'intégration avec les outils de l'écosystème Docker.Les bind mounts sont utiles lorsque vous devez accéder directement à des fichiers ou des répertoires depuis l’hôte dans le conteneur.

Ce tableau est issu de ce site, je n'ai fait que le traduire.

Donc pour résumer au minima du minima:

  • les volumes docker => les dossiers ne sont pas montés dans le container même => si vous supprimez le dossier de votre container vos données ne sont pas effacées dans la foulée vu qu'elles ne se trouvent pas dedans.
  • les bind mounts => les dossiers sont directement montés dans le container => si vous supprimez le dossier du container pour une raison ou une autre, il faudra veiller à déplacer vos données avant sans quoi tout est perdu.

Maintenant voyons comment cela se traduit dans un docker-compose.

La majorité du temps vous allez tomber sur trois cas de figure. Pour illustrer cela, nous allons prendre le même docker-compose et l'adapter pour chaque situation.

Prenons le docker-compose de Homarr. Il est simple, pas trop long ni compliqué, notre attention sur les volumes sera ainsi facilitée.

Attention, un docker-compose simple ne veut absolument pas dire que l'application n'est pas bonne ou simple.

Cas de figure numéro 1

Ici nous sommes dans le cas d'un bind mounts, les données sont montées dans le container.

version: '3'

services:
  homarr:
    container_name: homarr
    image: ghcr.io/ajnart/homarr:latest
    restart: unless-stopped
    volumes:
      - ./homarr/configs:/app/data/configs
      - ./homarr/icons:/app/public/icons
      - ./homarr/data:/data
    ports:
      - '7575:7575'

Dans cette configuration, on voit que l'indication de où doivent se trouver les données commence par ./, à première vue cela ne donne pas beaucoup d'indices pour comprendre où vont être stockées ces maudites données...

En réalité, la solution est toute simple: tout dépend dans quel répertoire vous vous trouvez. En effet, il suffit de penser quand vous voyez ça: "Quand je vais lancer mon docker-compose, cela va créer les dossiers qui suivent ./ dans le dossier dans lequel je me trouve."

Prenons l'exemple que vous voyez dans les tutoriels de belginux, qui est purement arbitraire: /srv/appdata.
Pour m'y retrouver, je réunis toutes mes applications dans un dossier qui se nomme appdata.

Donc si je déploie ce docker-compose dans le dossier /appdata, le dossier homarr sera créé dans: /srv/appdata, ce qui va donner /srv/appdata/homarr, et évidemment dans ce dossier homarr vont-être créés:

  • configs
  • icones
  • data

Donc l'endroit d'où vous déployez votre docker-compose est important. Ne vous trompez pas. 😀

En image cela donne ceci:

Je fais la commande ls pour lister le contenu du dossier ou je me trouve:

On voit clairement qu'il n'y a pas de dossier homarr. Maintenant je crée mon docker-compose:

Et je colle mon docker-compose:

Maintenant je vais le déployer:

Une fois que c'est terminé, je fais à nouveau ls pour lister le contenu:

On constate que le dossier homarr a bien été créé! Allons voir dedans:

Non seulement le dossier homarr a bien été créé, mais ses sous-dossiers également.


Cas de figure numéro 2

Ici nous sommes toujours dans le cas d'un bind mounts, les données sont dans le container.

Un autre exemple, qui est celui que vous trouverez dans la majorités des tutoriels sur belginux et d'autres sites parfois également:

version: '3'

services:
  homarr:
    container_name: homarr
    image: ghcr.io/ajnart/homarr:latest
    restart: unless-stopped
    volumes:
      - /srv/appdata/homarr/configs:/app/data/configs
      - /srv/appdata/homarr/icons:/app/public/icons
      - /srv/appdata/homarr/data:/data
    ports:
      - '7575:7575'

Cette façon ne laisse aucun doute possible, le chemin du dossier est complet et quelque soit le dossier d'où vous lancez votre docker-compose, cela n'a pas d'importance, il va créer homarr (et ses sous-dossiers) dans /srv/appdata.

Docker n'étant pas stupide, ce qui est déjà créé comme dossiers, il va simplement se dire ok, ça existe déjà, je vais passer au suivant et créer ceux qui manquent.

On supposant que srv et appdata soient déjà en place, Docker va comprendre qu'il doit simplement créer homarr et ses sous-dossiers afin que le chemin corresponde à ce qu'on lui a demandé dans le docker-compose.

En image cela donne:

J'ai donc effacé le dossier homarr:

Je vais éditer mon docker-compose:

Maintenant je vais le déployer et faire un ls:

Comme tout à l'heure, le dossier homarr est bien créé. Vous allez me dire, oui mais il n'y a pas de différence finalement? Et bien vous avez raison, les deux façons parviennent au même résultat. Ce n'est qu'une toute petite nuance entre ./ et le chemin complet.


Cas de figure numéro 3

Ici nous sommes dans le cas d'un docker volumes. Excepté pour le dossier config. N'en tenez pas compte.

Et maintenant le dernier cas, peut-être bien le plus "perturbant":

version: '3'

services:
  homarr:
    container_name: homarr
    image: ghcr.io/ajnart/homarr:latest
    restart: unless-stopped
    volumes:
      - ./homarr/configs:/app/data/configs
      - homarr-icons:/app/public/icons
      - homarr-data:/data
    ports:
      - '7575:7575'

volumes:
  homarr-icons:
  homarr-data:

Ici les volumes pour icons et data sont les volumes qui vont contenir de données.

Voyons de plus près:

- homarr-icons:/app/public/icons
- homarr-data:/data

Qui sont liés à:

volumes:
  homarr-icons:
  homarr-data:

Généralement ces deux indications vont de pair.

Si non quand vous allez déployer le docker-compose, et bien il va refuser de faire quoi que ce soit. Vous aurez un message de ce type:

Cette façon de renseigner les volumes indique à votre docker-compose qu'il doit créer les volumes de données dans le dossier volumes qui se trouve ou est installé Docker:

/var/lib/docker/volumes

À l'instar du cas de figure numéro 2, cela n'a aucune importance d'où vous lancer votre docker-compose.

Maintenant voyons tout ceci en image:

Je pars à nouveau sans homarr d'installé:

Je vais éditer mon docker-compose pour qu'il corresponde à notre exemple de docker volumes:

Maintenant je vais déployer le docker-compose.

Le dossier d'homarr a bien été créé:

MAIS, dedans, il n'y a plus que le dossier configs pour le fichier config:

Les données sont bien dans /var/lib/docker/volumes


Conclusion

Quelle est la meilleure méthode? Et bien c'est, pour ma part, un peu difficile à trancher, les deux ont des avantages et des inconvénients.

Quand on débute, ce qui est certain, c'est que c'est plus simple d'avoir tout au même endroit avec un chemin de dossier bien défini.

Les plus confirmés ou, voir les pros, vont généralement préférer la méthode docker volumes (ce que je remarque régulièrement). Cela à du sens si on part du postulat que si, par exemple, on a un dossier avec toutes nos photos, il vaut mieux que ce dossier soit hors du container, comme ça si jamais vous vouliez changer d'application photo, vous n'avez qu'à détruire le dossier du container et installer une autre application en lui indiquant les docker volumes.

Personnellement, les applications que j'utilise, je les utilise car j'en ai testé pleins d'autres et je sais que je vais me fixer un moment dessus, donc pour faciliter le tout, y compris mes backup, j'utilise la méthode bind mounts. Mais c'est un choix personnel et cela n'engage que moi. Même sans ça, je test en profondeur une application et quand elle me plaît, j'ajoute mes données par après vu que j'ai plusieurs backups sur des disques durs.

Le principal est de se faire plaisir avec notre petit serveur et d'évoluer à son aise. De toute facçon que vous choisissiez les docker volumes ou les blind mounts, à l'utilisation vous ne remarquerez aucune différence.

Je ne suis pas un professionnel mais j'essaye de ne pas trop chier dans la colle non plus.

J'espère que c'est un peu plus clair pour vous, n'hésitez jamais à diversifier vos sources pour apprendre et comprendre. D'ailleurs voici un lien qui peut-être bien complémentaire:

Les différences entre volumes et mounts dans Docker · Guillaume Fenollar - Administrateur Système Linux | DevOps Kubernetes - Nouméa
Il y a plusieurs façons de stocker de la donnée persistante dans une architecture Docker. L’idée étant bien sûr de ne pas perdre ses données à la destruction de ses conteneurs Docker, qu’elle soit volontaire ou non. En effet, la bonne pratique dans l’utilisation de conteneurs Docker quand un redémarrage du service est requis, est de regénérer un conteneur neuf à partir de son image au lieu de le stopper/redémarrer comme un nouveau-venu serait tenté de faire. Ce comportement est d’ailleurs le seul possible dans le cas d’une infrastructure Kubernetes.

Si jamais...

Si vous avez la moindre difficulté, n'oubliez pas que vous pouvez rejoindre belginux sur Discord et Matrix!

Bonne journée à toi.

zarev

🐧 Passionné de self-hosting, je partage ce que je connais et me nourris des connaissances des bonnes âmes qui partagent avec moi. Soutenons l'utilisation des apps open source et leurs développeurs.