Question d'origine: comment utiliser l'instruction VOLUME dans Dockerfile?
La vraie question que je veux résoudre est - comment monter des volumes hôtes dans des conteneurs Docker dans Dockerfile pendant la construction, c'est-à-dire avoir la docker run -v /export:/export
capacité pendant docker build
.
La raison derrière cela, pour moi, est lors de la construction de choses dans Docker, je ne veux pas que ces apt-get install
caches ( ) soient verrouillés dans un seul docker, mais pour les partager / réutiliser. C'est la principale raison pour laquelle je pose cette question.
Dernière mise à jour:
Avant Docker v18.09, la bonne réponse devrait être celle qui commence par:
Il existe un moyen de monter un volume pendant une génération, mais cela n'implique pas Dockerfiles.
Cependant, c'était une réponse mal formulée, organisée et appuyée. Lorsque j'ai réinstallé mon docker contient, je suis tombé sur l'article suivant:
Docker un service apt-cacher-ng
https://docs.docker.com/engine/examples/apt-cacher-ng/
C'est la solution du docker à cette / ma question, pas directement mais indirectement. C'est la manière orthodoxe que Docker nous propose de faire. Et j'avoue que c'est mieux que celui que j'essayais de demander ici.
Une autre façon est la nouvelle réponse acceptée , par exemple, le Buildkit dans la version 18.09.
Choisissez celui qui vous convient.
Était: Il y avait eu une solution - rocker, qui n'était pas de Docker, mais maintenant que le rocker est interrompu, je reviens à la réponse "Pas possible" .
Ancienne mise à jour: la réponse est donc "impossible". Je peux l'accepter comme réponse car je sais que le problème a été longuement discuté sur https://github.com/docker/docker/issues/3156 . Je peux comprendre que la portabilité est un problème primordial pour le développeur docker; mais en tant qu'utilisateur docker, je dois dire que je suis très déçu de cette fonctionnalité manquante. Permettez-moi de terminer mon argumentation par une citation de la discussion susmentionnée: " Je voudrais utiliser Gentoo comme image de base, mais je ne veux certainement pas que> 1 Go de données d'arborescence Portage soient dans l'une des couches une fois l'image créée. Vous pourrait avoir de jolis conteneurs compacts sans le gigantesque arbre de portage devant apparaître dans l'image lors de l'installation."Oui, je peux utiliser wget ou curl pour télécharger tout ce dont j'ai besoin, mais le fait qu'une simple considération de portabilité m'oblige maintenant à télécharger> 1 Go d'arborescence Portage chaque fois que je crée une image de base Gentoo n'est ni efficace ni convivial. de plus, le dépôt de paquets SERA TOUJOURS sous / usr / portage, donc TOUJOURS PORTABLE sous Gentoo. Encore une fois, je respecte la décision, mais permettez-moi d'exprimer ma déception également dans l'intervalle. Merci.
Question originale en détail:
De
Partager des répertoires via des volumes
http://docker.readthedocs.org/en/v0.7.3/use/working_with_volumes/
il indique que la fonctionnalité de volumes de données "est disponible depuis la version 1 de l'API Docker Remote". Mon docker est de la version 1.2.0, mais j'ai trouvé que l'exemple donné dans l'article ci-dessus ne fonctionnait pas:
# BUILD-USING: docker build -t data .
# RUN-USING: docker run -name DATA data
FROM busybox
VOLUME ["/var/volume1", "/var/volume2"]
CMD ["/usr/bin/true"]
Quelle est la bonne façon dans Dockerfile de monter des volumes montés sur l'hôte dans des conteneurs Docker, via la commande VOLUME?
$ apt-cache policy lxc-docker
lxc-docker:
Installed: 1.2.0
Candidate: 1.2.0
Version table:
*** 1.2.0 0
500 https://get.docker.io/ubuntu/ docker/main amd64 Packages
100 /var/lib/dpkg/status
$ cat Dockerfile
FROM debian:sid
VOLUME ["/export"]
RUN ls -l /export
CMD ls -l /export
$ docker build -t data .
Sending build context to Docker daemon 2.56 kB
Sending build context to Docker daemon
Step 0 : FROM debian:sid
---> 77e97a48ce6a
Step 1 : VOLUME ["/export"]
---> Using cache
---> 59b69b65a074
Step 2 : RUN ls -l /export
---> Running in df43c78d74be
total 0
---> 9d29a6eb263f
Removing intermediate container df43c78d74be
Step 3 : CMD ls -l /export
---> Running in 8e4916d3e390
---> d6e7e1c52551
Removing intermediate container 8e4916d3e390
Successfully built d6e7e1c52551
$ docker run data
total 0
$ ls -l /export | wc
20 162 1131
$ docker -v
Docker version 1.2.0, build fa7b24f
VOLUME ~/host_dir ~/container_dir
. La discussion est assez approfondie, s'il y a un court moyen de résumer quelle est la raison?Réponses:
Tout d'abord, pour répondre "pourquoi ne
VOLUME
fonctionne pas ?" Lorsque vous définissez unVOLUME
dans le Dockerfile, vous ne pouvez définir que la cible, pas la source du volume. Pendant la construction, vous n'en obtiendrez qu'un volume anonyme. Ce volume anonyme sera monté à chaqueRUN
commande, prérempli avec le contenu de l'image, puis supprimé à la fin de laRUN
commande. Seules les modifications apportées au conteneur sont enregistrées, pas les modifications du volume.Depuis que cette question a été posée, quelques fonctionnalités ont été publiées qui pourraient aider. Le premier est les constructions à plusieurs étapes vous permettant de créer une première étape d'espace disque inefficace et de copier uniquement la sortie nécessaire dans la dernière étape que vous expédiez. Et la deuxième fonctionnalité est Buildkit qui change radicalement la façon dont les images sont construites et de nouvelles capacités sont ajoutées à la construction.
Pour une construction en plusieurs étapes, vous auriez plusieurs
FROM
lignes, chacune commençant la création d'une image distincte. Seule la dernière image est balisée par défaut, mais vous pouvez copier des fichiers des étapes précédentes. L'utilisation standard est d'avoir un environnement de compilation pour construire un artefact binaire ou autre application, et un environnement d'exécution comme deuxième étape qui copie sur cet artefact. Tu aurais pu:Cela entraînerait une génération qui ne contient que le binaire résultant, et non le répertoire complet / export.
Buildkit sort de l'expérimental le 18.09. C'est une refonte complète du processus de construction, y compris la possibilité de changer l'analyseur frontal. L'une de ces modifications de l'analyseur a mis en œuvre l'
RUN --mount
option qui vous permet de monter un répertoire de cache pour vos commandes d'exécution. Par exemple, voici celui qui monte certains des répertoires debian (avec une reconfiguration de l'image debian, cela pourrait accélérer les réinstallations des paquets):Vous devez ajuster le répertoire de cache pour le cache d'application dont vous disposez, par exemple $ HOME / .m2 pour maven, ou /root/.cache pour golang.
TL; DR: La réponse est ici: Avec cette
RUN --mount
syntaxe, vous pouvez également lier des répertoires en lecture seule à partir du contexte de construction. Le dossier doit exister dans le contexte de génération et il n'est pas mappé vers l'hôte ou le client de génération:Notez que le répertoire étant monté à partir du contexte, il est également monté en lecture seule et vous ne pouvez pas renvoyer les modifications à l'hôte ou au client. Lorsque vous construisez, vous souhaiterez une installation 18.09 ou plus récente et activez buildkit avec
export DOCKER_BUILDKIT=1
.Si vous obtenez une erreur indiquant que l'indicateur de montage n'est pas pris en charge, cela indique que vous n'avez pas activé buildkit avec la variable ci-dessus, ou que vous n'avez pas activé la syntaxe expérimentale avec la ligne de syntaxe en haut du Dockerfile avant toute autre ligne, y compris les commentaires. Notez que la variable pour basculer buildkit ne fonctionnera que si votre installation de docker a un support de buildkit intégré, qui nécessite la version 18.09 ou plus récente de Docker, à la fois sur le client et le serveur.
la source
Il n'est pas possible d'utiliser l'
VOLUME
instruction pour indiquer à docker quoi monter. Cela romprait sérieusement la portabilité. Cette instruction indique à docker que le contenu de ces répertoires ne va pas dans les images et est accessible à partir d'autres conteneurs à l'aide du--volumes-from
paramètre de ligne de commande. Vous devez exécuter le conteneur en utilisant-v /path/on/host:/path/in/container
pour accéder aux répertoires de l'hôte.Il n'est pas possible de monter des volumes d'hôtes pendant la génération. Il n'y a pas de construction privilégiée et le montage de l'hôte dégraderait également sérieusement la portabilité. Vous voudrez peut-être essayer d'utiliser wget ou curl pour télécharger tout ce dont vous avez besoin pour la construction et le mettre en place.
la source
MISE À JOUR: Quelqu'un ne prendra tout simplement pas non comme réponse, et j'aime beaucoup, surtout à cette question particulière.
BONNES NOUVELLES, il y a un moyen maintenant -
La solution est Rocker: https://github.com/grammarly/rocker
John Yani a déclaré : "IMO, il résout tous les points faibles de Dockerfile, ce qui le rend apte au développement."
Bascule
https://github.com/grammarly/rocker
Mise à jour: Rocker a été interrompu, selon le référentiel officiel du projet sur Github
la source
MOUNT ~/code/docker-app-dev/new-editor/:/src/
et ma commande de construction Rocker est la suivante -rocker build -f Dockerfile .
. Qu'est-ce que je fais mal?~
est un métacaractère du shell Bourne.Rocker build
ne permet pas lesdocker run
options de ligne de commande, donc ne permet pas actuellement des choses comme--privileged
.Il existe un moyen de monter un volume pendant une génération, mais cela n'implique pas Dockerfiles.
La technique consiste à créer un conteneur à partir de la base que vous souhaitez utiliser (monter votre ou vos volumes dans le conteneur avec l'
-v
option), exécuter un script shell pour effectuer votre travail de création d'image, puis valider le conteneur en tant qu'image lorsque vous avez terminé .Non seulement cela laissera de côté les fichiers excédentaires dont vous ne voulez pas (c'est également bon pour les fichiers sécurisés, comme les fichiers SSH), mais cela crée également une seule image. Il a des inconvénients: la commande commit ne prend pas en charge toutes les instructions Dockerfile, et elle ne vous permet pas de reprendre lorsque vous vous êtes arrêté si vous devez modifier votre script de construction.
METTRE À JOUR:
Par exemple,
la source
debian:wheezy
et le script shellbuild.sh
, quelles instructions spécifiques utiliserait-on?Lorsque vous exécutez le conteneur, un répertoire sur votre hôte est créé et monté dans le conteneur. Vous pouvez savoir de quel répertoire il s'agit
Si vous souhaitez monter un répertoire à partir de votre hôte à l'intérieur de votre conteneur, vous devez utiliser le
-v
paramètre et spécifier le répertoire. Dans votre cas, ce serait:Vous utiliserez donc le dossier hosts à l'intérieur de votre conteneur.
la source
Je pense que vous pouvez faire ce que vous voulez en exécutant la construction via une commande docker qui elle-même est exécutée dans un conteneur docker. Voir Docker peut désormais s'exécuter dans Docker | Blog Docker . Une technique comme celle-ci, mais qui accédait en fait au docker externe à partir d'un conteneur, a été utilisée, par exemple, pour explorer comment créer le plus petit conteneur Docker possible | Blog Xebia .
Un autre article pertinent est Optimisation des images Docker | CenturyLink Labs , qui explique que si vous finissez par télécharger des trucs pendant une construction, vous pouvez éviter de perdre de l'espace dans l'image finale en téléchargeant, construisant et supprimant le téléchargement en une seule étape RUN.
la source
C'est moche, mais j'ai réalisé un semblant de ceci comme ceci:
Dockerfile:
imageBuild.sh:
J'ai une version java qui télécharge l'univers dans /root/.m2, et je l'ai fait à chaque fois .
imageBuild.sh
copie le contenu de ce dossier sur l'hôte après la génération et lesDockerfile
copie dans l'image pour la génération suivante.C'est quelque chose comme le fonctionnement d'un volume (c'est-à-dire qu'il persiste entre les builds).
la source
Voici une version simplifiée de l'approche en 2 étapes utilisant la génération et la validation, sans scripts shell. Ça implique:
Avec des modifications relativement mineures, l'étape supplémentaire n'ajoute que quelques secondes au temps de construction.
Fondamentalement:
Dans mon cas d'utilisation, je souhaite pré-générer un fichier maven toolchains.xml, mais mes nombreuses installations JDK se trouvent sur un volume qui n'est pas disponible avant l'exécution. Certaines de mes images ne sont pas compatibles avec tous les JDKS, je dois donc tester la compatibilité au moment de la construction et remplir conditionnellement toolchains.xml. Notez que je n'ai pas besoin que l'image soit portable, je ne la publie pas sur Docker Hub.
la source
Comme beaucoup l'ont déjà répondu, le montage de volumes d'hôtes pendant la génération n'est pas possible. Je voudrais juste ajouter un
docker-compose
moyen, je pense que ce sera bien d'avoir, principalement pour le développement / l'utilisation des testsDockerfile
docker-compose.yml
Et exécutez votre conteneur par
docker-compose up -d --build
la source