Docker ADD vs VOLUME

116

J'apprends Docker et j'ai des doutes sur quand et où utiliser ADDet VOLUME. Voici ce que je pense que les deux font:

AJOUTER

Copiez les fichiers sur l'image au moment de la construction. L'image contient tous les fichiers afin que vous puissiez le déployer très facilement. D'un autre côté, avoir besoin de construire à chaque fois ne semble pas être une bonne idée en développement car la construction nécessite que le développeur exécute une commande pour reconstruire le conteneur; de plus, la construction du conteneur peut prendre du temps.

LE VOLUME

Je comprends qu'en utilisant docker run -vvous pouvez monter un dossier hôte dans votre conteneur, de cette façon, vous pouvez facilement modifier les fichiers et regarder l'application dans votre conteneur réagir aux modifications. Cela a l'air bien en développement, mais je ne sais pas comment déployer mes fichiers de cette façon.

Cristian Garcia
la source
3
En général, il est préférable de préférer COPYà ADD. Ils sont presque les mêmes, mais ADDont des capacités supplémentaires pour les URL et les fichiers d'archive qui peuvent être surprenantes.
Adrian Mouat
2
@jamesmstone - ce lien (et les documents officiels de docker) recommandent le contraire - utilisez COPY plutôt que ADD.
Software Engineer
oups, vous avez raison - bravo!
jamesmstone

Réponses:

183

AJOUTER

La différence fondamentale entre ces deux éléments est que ADDtout ce que vous ajoutez, que ce soit un dossier ou juste un fichier, fait partie de votre image . Quiconque utilise l'image que vous avez créée par la suite aura accès à tout ce que vous ADD. Cela est vrai même si vous le supprimez par la suite, car Docker fonctionne en couches et la ADDcouche existera toujours dans le cadre de l'image. Pour être clair, vous n'avez que ADDquelque chose au moment de la construction et ne pouvez jamais ADDau moment de l'exécution.

Quelques exemples de cas où vous souhaiteriez utiliser ADD:

  • Vous avez certaines exigences dans un fichier requirements.txt que vous souhaitez référencer et installer dans votre Dockerfile. Vous pouvez alors faire: ADD ./requirements.txt /requirements.txtsuivi deRUN pip install -r /requirements.txt
  • Vous souhaitez utiliser le code de votre application comme contexte dans votre Dockerfile, par exemple, si vous souhaitez définir votre répertoire d'application comme répertoire de travail dans votre image et que la commande par défaut dans un conteneur exécuté à partir de votre image exécute réellement votre application, vous peut faire:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

LE VOLUME

Volume, d'autre part, permet simplement à un conteneur exécuté à partir de votre image d'accéder à un chemin sur n'importe quelle machine locale sur laquelle le conteneur est exécuté. Vous ne pouvez pas utiliser les fichiers de votre VOLUMErépertoire dans votre Dockerfile . Tout ce qui se trouve dans votre répertoire de volume ne sera pas accessible au moment de la construction, mais le sera au moment de l'exécution .

Quelques exemples de cas où vous souhaiteriez utiliser VOLUME:

  • L'application en cours d'exécution dans votre conteneur se connecte /var/log/my_app. Vous souhaitez que ces journaux soient accessibles sur la machine hôte et ne soient pas supprimés lorsque le conteneur est supprimé. Vous pouvez le faire en créant un point de montage sur /var/log/my_appen l'ajoutant VOLUME /var/log/my_appà votre Dockerfile, puis en exécutant votre conteneur avecdocker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag
  • Vous disposez de certains fichiers de paramètres locaux auxquels vous souhaitez que l'application dans le conteneur ait accès. Peut-être que ces fichiers de paramètres sont différents sur votre ordinateur local par rapport au développement et à la production. Surtout si ces fichiers de paramètres sont secrets, auquel cas vous ne les voulez certainement pas dans votre image . Une bonne stratégie dans ce cas est d'ajouter VOLUME /etc/settings/my_app_settingsà votre Dockerfile, d'exécuter votre conteneur avec docker run -v /host/settings/dir:/etc/settings/my_app_settings some_repo/some_image:some_taget de vous assurer que le / host / settings / dir existe dans tous les environnements dans lesquels vous vous attendez à ce que votre application soit exécutée.
Eli
la source
13
De loin le post le plus utile que j'ai trouvé jusqu'à présent sur ADD and VOLUME
Jasmeet
5
Que se passe-t-il si VOLUME est spécifié, mais non fourni pendant l'exécution du docker (par exemple, le paramètre -v xxx est manquant)? Est le resp. VOLUME devient alors effectivement transitoire?
col.panic
Dans un Dockerfile, les volumes ne sont probablement destinés qu'à la persistance et / ou au débogage, mais vous pouvez utiliser le commutateur de ligne de commande de volume pour obtenir une application dans une image existante (aucun Dockerfile nécessaire) et l'exécuter comme ceci docker run -v $HOST_PATH:$CONTAINER_PATH node:latest node $CONTAINER_PATH/app.js.
Chinoto Vokro
joli "layer" detail
stratovarius
27

L' VOLUMEinstruction crée un volume de données dans votre conteneur Docker au moment de l'exécution. Le répertoire fourni en tant qu'argument VOLUMEest un répertoire qui contourne le système de fichiers Union et est principalement utilisé pour les données persistantes et partagées.

Si vous exécutez docker inspect <your-container>, vous verrez dans la Mountssection il y a un Sourcequi représente l'emplacement du répertoire sur l'hôte, et un Destinationqui représente l'emplacement du répertoire monté dans le conteneur. Par exemple,

"Mounts": [
  {
    "Name": "fac362...80535",
    "Source": "/var/lib/docker/volumes/fac362...80535/_data",
    "Destination": "/webapp",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

Voici 3 cas d'utilisation pour docker run -v:

  1. docker run -v /data: Cela revient à spécifier l' VOLUMEinstruction dans votre Dockerfile.
  2. docker run -v $host_path:$container_path: Cela vous permet d'effectuer un montage $host_pathdepuis votre hôte vers $container_pathvotre conteneur pendant l'exécution. En développement, cela est utile pour partager du code source sur votre hôte avec le conteneur. En production, cela peut être utilisé pour monter des éléments tels que les informations DNS de l'hôte (trouvées dans /etc/resolv.conf) ou des secrets dans le conteneur. Inversement, vous pouvez également utiliser cette technique pour écrire les journaux du conteneur dans des dossiers spécifiques sur l'hôte. Les deux $host_pathet $container_pathdoivent être des chemins absolus.
  3. docker run -v my_volume:$container_path: Cela crée un volume de données dans votre conteneur à $container_pathet le nomme my_volume. C'est essentiellement la même chose que de créer et de nommer un volume à l'aide de docker volume create my_volume. Nommer un volume comme celui-ci est utile pour un volume de données de conteneur et un volume de stockage partagé à l'aide d'un pilote de stockage multi-hôte comme Flocker .

Notez que l'approche consistant à monter un dossier hôte en tant que volume de données n'est pas disponible dans Dockerfile. Pour citer la documentation du docker ,

Remarque: Ceci n'est pas disponible à partir d'un Dockerfile en raison de sa portabilité et de son objectif de partage. Comme le répertoire hôte est, de par sa nature, dépendant de l'hôte, un répertoire hôte spécifié dans un Dockerfile ne fonctionnera probablement pas sur tous les hôtes.

Désormais, si vous souhaitez copier vos fichiers dans des conteneurs dans des environnements sans développement, vous pouvez utiliser les instructions ADDou COPYde votre Dockerfile. C'est ce que j'utilise habituellement pour un déploiement hors développement.

ivan.sim
la source
3
Dois-je créer 2 fichiers docker? Un pour le développement et un pour le déploiement?
Cristian Garcia
Je ne pense pas. Il n'y a rien de mal à avoir l' ADDinstruction dans votre Dockerfile, car elle n'est exécutée que par la docker buildcommande. Cela est nécessaire lorsque d'autres personnes créent votre conteneur pour la première fois et lorsque vous êtes prêt à le déployer dans d'autres environnements hors développement.
ivan.sim
3
Mais ne serait-il pas plus efficace de créer une image sans les fichiers et d'utiliser la -vcommande pour le développement, et de demander à un autre fichier docker de créer une image qui inclut les fichiers avec ADDpour le déploiement?
Cristian Garcia
1
C'est un compromis que vous devez décider. Choisissez ce qui fonctionne pour vous. Combien de temps dure la construction avec un ADD? Quelques secondes au total? Si vous avez deux fichiers Dockerfile et que vous le partagez avec d'autres (ou le publiez sur le registre Docker ), lequel est celui par défaut? Vous aurez des frais de maintenance supplémentaires pour vous assurer que le bon Dockerfile par défaut parvient aux bons utilisateurs. Mais à la fin de la journée, vous décidez de ce qui vous convient le mieux. Personnellement, j'aime m'assurer qu'il n'y a qu'un et un seul Dockerfile pour construire mon conteneur.
ivan.sim
11
Au fait, je pense que c'est bien de commencer par AJOUTER, puis de remplacer cet ajout par -v pour le développement. De cette façon, vous n'aurez pas besoin de fichiers Docker séparés.
Attila Szeremi