docker montage des volumes sur l'hôte

135

J'ai réussi à partager des dossiers entre un conteneur Docker avec des volumes en utilisant

docker run -v /host/path:/container/path ...

Mais ma question est de savoir quelle est la différence entre cela et l'utilisation de la VOLUMEcommande dans le Dockerfile

VOLUME /path

J'utilise une image avec une VOLUMEcommande et j'aimerais savoir comment la partager avec mon hôte. Je l'ai fait en utilisant la -vcommande ci-dessus, mais je ne savais pas si j'avais besoin à la fois de -vet VOLUME.

Jeff Storey
la source

Réponses:

155

La VOLUMEcommande montera un répertoire à l'intérieur de votre conteneur et stockera tous les fichiers créés ou modifiés dans ce répertoire sur votre disque hôte en dehors de la structure de fichiers du conteneur , en contournant le système de fichiers union.

L'idée est que vos volumes peuvent être partagés entre vos conteneurs docker et qu'ils resteront en place tant qu'il y aura un conteneur (en cours d'exécution ou arrêté) qui les référencera.

Vous pouvez demander à d'autres conteneurs de monter des volumes existants (en les partageant efficacement entre conteneurs) à l'aide de la --volumes-fromcommande lorsque vous exécutez un conteneur.

La différence fondamentale entre VOLUMEet -vest la suivante: -vva monter des fichiers existants de votre système d'exploitation à l' intérieur de votre conteneur docker et VOLUMEva créer un nouveau, le volume vide sur votre hôte et le monter à l' intérieur de votre récipient.

Exemple:

  1. Vous avez un Dockerfile qui définit un fichier VOLUME /var/lib/mysql.
  2. Vous créez l'image du docker et vous la marquez some-volume
  3. Vous exécutez le conteneur

Puis,

  1. Vous avez une autre image de menu fixe que vous souhaitez utiliser ce volume
  2. Vous exécutez le conteneur Docker avec les éléments suivants: docker run --volumes-from some-volume docker-image-name:tag
  3. Maintenant, vous avez un conteneur docker en cours d'exécution qui aura le volume de some-volumemonté dans/var/lib/mysql

Remarque: Utiliser --volumes-frommontera le volume sur tout ce qui existe à l'emplacement du volume. Par exemple, si vous aviez /var/lib/mysqldu contenu, il sera remplacé par le contenu du volume.

Chris McKinnel
la source
12
Que se passe-t-il si j'utilise -v sur un répertoire déjà spécifié dans VOLUME?
Jeff Storey
6
--volumes-frommontera votre VOLUMEpar-dessus tout ce que vous spécifiez avec -v. Fait intéressant, il semble que l' exécution du conteneur en mode privilégié ( docker run --privileged) et umounting /var/lib/mysqlva juste laisser un répertoire vide de sorte que votre -vmonture est complètement ignoré quand il est en conflit avec VOLUME.
Chris McKinnel
2
Vous dites que les volumes sont conservés tant qu'un conteneur y fait référence, et j'ai vu cela ailleurs. docs.docker.com/userguide/dockervolumes dit: "Les volumes de données sont conçus pour conserver les données, indépendamment du cycle de vie du conteneur. Docker ne supprime donc jamais automatiquement les volumes lorsque vous supprimez un conteneur, et il ne" récupère pas "les volumes qui ne sont plus référencé par un conteneur. " L'une de ces déclarations doit être erronée.
mc0e
1
Les fichiers qui se trouvent dans le volume sont conservés sur le disque lorsqu'un conteneur ne le référence plus, mais le volume lui-même n'est plus utilisable (à moins que vous ne sachiez exactement comment connecter manuellement un volume à un conteneur, mais même dans ce cas, je ne le fais pas) t savoir si cela est possible). Quand je dis plus utilisable, je veux dire que vous ne pouvez pas utiliser --volumes-from pour l'utiliser. Lorsqu'ils disent «ramassage des ordures» ci-dessus, ils signifient supprimer les fichiers de votre disque qui se trouvaient dans le volume.
Chris McKinnel
1
Ils sont utilisables avec -v, mais pas avec --volumes-from. Volumes-from prend un nom de conteneur pour récupérer les données de volume (je crois que cela prend TOUS les points de volume). Pour -v lui-même, cependant, le manuel mentionne que vous pouvez fournir un volume nommé à -v sous la forme de named-volume:/path/in/container. Les volumes sans nom reçoivent des hachages pour les noms et ces hachages peuvent être fournis à la place d'un chemin d'hôte pour accéder aux volumes orphelins. :) Soyez conscient que volume lspeut ne pas les montrer tous - essayez docker volume ls -f dangling=trueaussi.
Jasmine Hegman
44

Permettez-moi d'ajouter ma propre réponse, car je pense que les autres manquent le point de Docker.

L'utilisation VOLUMEdans Dockerfile est la bonne façon ™, car vous faites savoir à Docker qu'un certain répertoire contient des données permanentes. Docker créera un volume pour ces données et ne le supprimera jamais, même si vous supprimez tous les conteneurs qui l'utilisent.

Il contourne également le système de fichiers union, de sorte que le volume est en fait un répertoire réel qui est monté (en lecture-écriture ou en lecture seule) au bon endroit dans tous les conteneurs qui le partagent.

Désormais, pour accéder à ces données depuis l'hôte, il vous suffit d'inspecter votre conteneur:

# docker inspect myapp
[{
    .
    .
    .
    "Volumes": {
        "/var/www": "/var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6...",
        "/var/cache/nginx": "/var/lib/docker/vfs/dir/62499e6b31cb3f7f59bf00d8a16b48d2...",
        "/var/log/nginx": "/var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87..."
    },
    "VolumesRW": {
        "/var/www": false,
        "/var/cache/nginx": true,
        "/var/log/nginx": true
    }
}]

Ce que je fais habituellement, c'est créer des liens symboliques dans un endroit standard tel que / srv , afin que je puisse facilement accéder aux volumes et gérer les données qu'ils contiennent (uniquement pour les volumes qui vous intéressent):

ln -s /var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6... /srv/myapp-www
ln -s /var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87... /srv/myapp-log
Tobia
la source
Que faire si l'hôte docker s'exécute dans une machine virtuelle? Par exemple, boot2docker sur mac. Ensuite, ces volumes ne sont disponibles qu'à distance. De plus, lorsque vous utilisez des volumes dans le Dockerfile comme vous l'avez décrit, le contenu de l'image sera copié sur le volume. Cependant, lors du montage dans un répertoire local, cette copie n'a pas lieu. Savez-vous pourquoi c'est le cas? Existe-t-il un moyen d'avoir un volume monté localement tout en «repartant à zéro» avec les fichiers de l'image?
LostSalad
4
avec docker-compose vous pouvez exactement faire cela, monter un volume sur un emplacement spécifique de l'os hôte . Aucun lien symbolique nécessaire ...
Hugo Koopmans
@Tobia: exemple docker-compose voir la documentation docs.docker.com/compose/compose-file/…
Hugo Koopmans
11

VOLUME est utilisé Dockerfilepour exposer le volume à utiliser par d'autres conteneurs. Exemple, créez Dockerfilecomme:

DEPUIS ubuntu: 14.04

RUN mkdir /myvol  
RUN echo "hello world" > /myvol/greeting  
VOLUME /myvol

construire l'image:

$ docker build -t testing_volume .

Exécutez le conteneur, dites container1:

$ docker run -it <image-id of above image> bash

Maintenant, exécutez un autre conteneur avec l'option volumes-from comme (say-container2)

$ docker run -it --volumes-from <id-of-above-container> ubuntu:14.04 bash

Vous obtiendrez toutes les données du /myvolrépertoire container1 dans container2 au même emplacement.

-vL'option est donnée au moment de l'exécution du conteneur qui est utilisé pour monter le répertoire du conteneur sur l'hôte. Il est simple à utiliser, il suffit de fournir une -voption avec un argument comme <host-path>:<container-path>. La commande entière peut être comme$ docker run -v <host-path>:<container-path> <image-id>

Yogesh Jilhawar
la source
8

Fondamentalement VOLUME, les -voptions sont presque égales. Cela signifie «monter un répertoire spécifique sur votre conteneur». Par exemple, VOLUME /dataet a -v /dataexactement la même signification. Si vous exécutez l'image VOLUME /dataavec ou avec -v /dataoption, le /datarépertoire est monté sur votre conteneur. Ce répertoire n'appartient pas à votre conteneur.

Imaginez que vous ajoutez des fichiers /datasur le conteneur, puis que vous confiez le conteneur dans une nouvelle image. Il n'y a aucun fichier dans le répertoire de données car le /datarépertoire monté appartient au conteneur d'origine.

$ docker run -it -v /data --name volume ubuntu:14.04 bash
root@2b5e0f2d37cd:/# cd /data
root@2b5e0f2d37cd:/data# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/data# cd /tmp
root@2b5e0f2d37cd:/tmp# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/tmp# exit
exit

$ docker commit volume nacyot/volume  
835cfe3d8d159622507ba3256bb1c0b0d6e7c1419ae32751ad0f925c40378945
nacyot $ docker run -it nacyot/volume
root@dbe335c7e64d:/# cd /data
root@dbe335c7e64d:/data# ls
root@dbe335c7e64d:/data# cd /tmp
root@dbe335c7e64d:/tmp# ls
1  2  3  4  5  6  7  8  9
root@dbe335c7e64d:/tmp# 
root@dbe335c7e64d:/tmp# 

Ce répertoire monté comme /dataest utilisé pour stocker des données qui n'appartiennent pas à votre application. Et vous pouvez prédéfinir le répertoire de données qui n'appartient pas au conteneur à l'aide de VOLUME.

Une différence entre Volumeet -voption est que vous pouvez utiliser l' -voption dynamiquement au démarrage du conteneur. Cela signifie que vous pouvez monter un répertoire dynamiquement. Et une autre différence est que vous pouvez monter votre répertoire hôte sur votre conteneur en utilisant-v

nacyot
la source
8

Cela provient de la documentation Docker elle-même, peut être utile, simple et claire:

"Le répertoire hôte est, de par sa nature, dépendant de l'hôte. Pour cette raison, vous ne pouvez pas monter un répertoire hôte à partir de Dockerfile, l'instruction VOLUME ne prend pas en charge le passage d'un répertoire hôte, car les images construites doivent être portables. Un hôte l'annuaire ne serait pas disponible sur tous les hôtes potentiels. ".

Vennesa
la source