En bref: Non, votre VOLUME
instruction n'est pas correct.
Dockerfile de l' VOLUME
spécifiez un ou plusieurs volumes de donnée contenant du côté des chemins. Mais il ne permet pas à l'image de l'auteur de spécifier un hôte chemin. Sur le côté hôte, les volumes sont créés avec un très long ID-nom à l'intérieur du Panneau de la racine. Sur ma machine, c'est - /var/lib/docker/volumes
.
Remarque: en Raison de l'généré automatiquement le nom est très long et n'a pas de sens à partir d'un humain du point de vue, ces volumes sont souvent désignés comme des "sans nom" ou "anonyme".
Votre exemple qui utilise un caractère '.' aura même pas fonctionner sur ma machine, peu importe si je fais le point de la première ou de la deuxième argument. Je reçois ce message d'erreur:
docker: réponse d'Erreur de démon: bec erreur d'exécution: container_linux.aller:265: à partir conteneur processus a entraîné "process_linux.aller:368: conteneur init causé \"ouvrir /dev/ptmx: aucun fichier ou répertoire\"".
Je sais que ce qui a été dit à ce moment est probablement pas très utile à quelqu'un d'essayer de comprendre VOLUME
et -v
et il n'est certainement pas une solution pour ce que vous essayez d'accomplir. Alors, je l'espère, les exemples qui suivent vont faire la lumière sur ces questions.
Minitutorial: Spécification des volumes
Compte tenu de cette Dockerfile:
FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2
(Pour les résultats de cette minitutorial, il ne fait aucune différence si nous spécifier vol1 vol2
ou /vol1 /vol2
- ne me demandez pas pourquoi)
Construire:
docker build -t my-openjdk
Exécuter:
docker run --rm -it my-openjdk
À l'intérieur du conteneur, exécutez ls
dans la ligne de commande et vous remarquerez deux répertoires existent; /vol1
et /vol2
.
L'exécution du conteneur crée également deux répertoires, ou "volumes", sur le côté hôte.
Tout en ayant le conteneur en cours d'exécution, exécutez docker volume ls
sur la machine hôte et vous verrez quelque chose comme ceci (j'ai remplacé la partie centrale de ce nom avec les trois points pour des raisons de concision):
DRIVER VOLUME NAME
local c984...e4fc
local f670...49f0
De retour dans le conteneur, exécutez touch /vol1/weird-ass-file
(crée un fichier vide à l'emplacement).
Ce fichier est maintenant disponible sur la machine hôte, dans une de la sans nom volumes lol. Il m'a fallu deux essais car j'ai d'abord essayé le premier volume, mais finalement, j'ai trouvé mon fichier dans le deuxième volume répertoriés, à l'aide de cette commande sur la machine hôte:
sudo ls /var/lib/docker/volumes/f670...49f0/_data
De même, vous pouvez essayer de supprimer ce fichier sur l'hôte et sera supprimée dans le conteneur.
Remarque: L' _data
le dossier est également appelé "point de montage".
La sortie du récipient, et liste les volumes sur l'ordinateur hôte. Ils sont allés. Nous avons utilisé l' --rm
drapeau lors de l'exécution du conteneur et cette option a pour effet de lingettes non seulement le récipient à la sortie, mais aussi les volumes.
Exécuter un nouveau conteneur, mais spécifier un volume à l'aide d' -v
:
docker run --rm -it -v /vol3 my-openjdk
Cela ajoute un troisième volume et de l'ensemble du système finit par avoir trois sans nom volumes. La commande aurait écrasé l'on a spécifié qu' -v vol3
. L'argument doit être un absolu chemin à l'intérieur du conteneur. Sur le côté hôte, le troisième volume est anonyme et réside avec les deux autres volumes en /var/lib/docker/volumes/
.
Il a été indiqué plus tôt que l' Dockerfile
peut ne pas correspondre à un hôte chemin qui sorte de poser un problème pour nous lorsque essayant de mettre des fichiers de l'hôte vers le réservoir en cours d'exécution. Un autre -v
de la syntaxe permet de résoudre ce problème.
Imaginez que j'ai un sous-dossier de mon projet de répertoire ./src
que je souhaite pour synchroniser /src
à l'intérieur du conteneur. Cette commande fait l'affaire:
docker run -it -v $(pwd)/src:/src my-openjdk
Des deux côtés de l' :
personnage s'attend à un chemin d'accès absolu. Côté gauche d'être un chemin d'accès absolu sur la machine hôte, côté droit d'être un chemin d'accès absolu à l'intérieur du conteneur. pwd
est une commande qui "impression en cours/répertoire de travail". Mettre la commande dans l' $()
prend le commandement à l'intérieur de la parenthèse, exécute un shell interne est exécuté et les rendements reprendre le chemin d'accès absolu à notre répertoire de projet.
Mettre tous ensemble, supposons que nous avons ./src/Hello.java
dans notre dossier de projet sur la machine hôte avec le contenu suivant:
public class Hello {
public static void main(String... ignored) {
System.out.println("Hello, World!");
}
}
Nous construisons cette Dockerfile:
FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello
Nous exécutez cette commande:
docker run -v $(pwd)/src:/src my-openjdk
Cette affiche "Hello, World!".
La meilleure partie est que vous êtes totalement libre de modifier les .fichier java avec un nouveau message pour une autre sortie sur une deuxième exécution, sans avoir à reconstruire l'image =)
Remarques finales
Je suis assez nouveau dans le Panneau, et le fameux "tutoriel" reflète les informations que j'ai recueillies à partir de 3 jours de ligne de commande hackathon. Je suis presque honteux, je n'ai pas été en mesure de fournir des liens vers d'anglais clair-comme la documentation de la sauvegarde de mes déclarations, mais honnêtement, je pense que cela est dû à un manque de documentation et de ne pas l'effort personnel. Je sais que les exemples fonctionnent comme annoncé à l'aide de mon installation actuelle qui est "Windows 10 -> Vagrant 2.0.0 -> menu fixe 17.09.0-ce".
Le tutoriel n'est pas de résoudre le problème de "comment pouvons-nous préciser le conteneur du chemin d'accès dans le Dockerfile et laisser la course de commande de ne spécifier l'hôte chemin". Il y a peut être une façon, je n'en ai pas trouvé.
Enfin, j'ai le pressentiment que la spécification VOLUME
dans le Dockerfile n'est pas seulement rare, mais c'est probablement la meilleure pratique consiste à ne jamais utiliser d' VOLUME
. Et ce pour deux raisons. La première raison que nous avons déjà identifiés: Nous ne pouvons pas spécifier l'hôte chemin - ce qui est une bonne chose, parce que les Dockerfiles devrait être très agnostique aux spécificités d'une machine hôte. Mais la deuxième raison est que les gens peuvent oublier d'utiliser le --rm
option lors de l'exécution du conteneur. On pourrait n'oubliez pas de retirer le récipient, mais oublier de supprimer le volume. De Plus, même avec le meilleur de la mémoire humaine, il pourrait être une tâche ardue pour savoir qui de toutes anonymes, les volumes sont sans danger pour le retirer.