web-dev-qa-db-fra.com

Quelle est la différence entre les commandes `COPY` et` ADD` dans un fichier Dockerfile?

Quelle est la différence entre les commandes COPY et ADD dans un fichier Docker, et quand utiliserais-je l’une sur l’autre?

COPY <src> <dest>

L'instruction COPY copiera les nouveaux fichiers de <src> et les ajoutera au système de fichiers du conteneur dans le chemin <dest>.

ADD <src> <dest>

L'instruction ADD copiera les nouveaux fichiers de <src> et les ajoutera au système de fichiers du conteneur dans le chemin <dest>.

1899
Steve

Vous devriez consulter la documentation ADD et COPY pour une description exhaustive de leurs comportements, mais en résumé, la principale différence est que ADD peut faire plus que COPY:

  • ADD permet à <src> d'être une URL
  • En se référant aux commentaires ci-dessous, la documentation ADD indique clairement que:

    Si est une archive tar locale dans un format de compression reconnu (identité, gzip, bzip2 ou xz), elle est décompressée en tant que répertoire. Les ressources provenant d'URL distantes ne sont pas décompressées.

Notez que les meilleures pratiques pour l'écriture de fichiers Dockerfiles suggèrent d'utiliser COPY où la magie de ADD n'est pas requise. Sinon, vous (étant donné que vous avez dû chercher cette réponse) risquez d'être surpris un jour lorsque vous voulez copier keep_this_archive_intact.tar.gz dans votre conteneur, mais que vous pulvérisez plutôt le contenu sur votre système de fichiers.

1905
icecrime

COPY est

Identique à 'ADD', mais sans la gestion des URL tar et distante.

Référence directement du code source .

398
caike

Il existe une documentation officielle à ce sujet: Meilleures pratiques pour l'écriture de fichiers Dockerfiles

Étant donné que la taille de l'image est importante, il est fortement déconseillé d'utiliser ADD pour extraire des packages à partir d'URL distantes. vous devriez utiliser curl ou wget à la place. De cette façon, vous pourrez supprimer les fichiers dont vous n’avez plus besoin une fois qu’ils ont été extraits, sans avoir à ajouter un autre calque à votre image.

RUN mkdir -p /usr/src/things \
  && curl -SL http://example.com/big.tar.gz \
    | tar -xJC /usr/src/things \
  && make -C /usr/src/things all

Pour les autres éléments (fichiers, répertoires) ne nécessitant pas la fonction d’extraction automatique de goudron de ADD, vous devez toujours utiliser COPY.

129
Victor Laskin

De la documentation Docker:

AJOUTER ou COPIER

Bien que ADD et COPY soient fonctionnellement similaires, COPY est généralement préférable. C’est parce qu’il est plus transparent que ADD. COPY ne prend en charge que la copie de base des fichiers locaux dans le conteneur, tandis qu'ADD présente certaines fonctionnalités (telles que l'extraction de fichiers TAR uniquement locale et la prise en charge d'URL distantes) qui ne sont pas immédiatement évidentes. Par conséquent, la meilleure utilisation de ADD est l'extraction automatique du fichier tar local dans l'image, comme dans ADD rootfs.tar.xz /.

Plus: Meilleures pratiques pour l'écriture de Dockerfiles

108
eddd

Si vous souhaitez ajouter un fichier xx.tar.gz à un conteneur /usr/local dans un conteneur, décompressez-le, puis supprimez le package compressé inutile.

Pour COPY:

COPY resources/jdk-7u79-linux-x64.tar.gz /tmp/
RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local
RUN rm /tmp/jdk-7u79-linux-x64.tar.gz

Pour ajouter:

ADD resources/jdk-7u79-linux-x64.tar.gz /usr/local/

ADD prend en charge l'extraction de goudron uniquement local. En plus, COPY utilisera trois couches, mais ADD n’utilisera qu’une couche.

37
BertLi

Docker docs: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy

"Bien que les fonctions ADD et COPY soient similaires sur le plan fonctionnel, COPY est généralement préférable. C’est parce qu’elle est plus transparente que ADD. COPY ne prend en charge que la copie de base des fichiers locaux dans le conteneur. ADD possède certaines fonctionnalités (comme l’extraction locale prise en charge d'URL distante) qui ne sont pas immédiatement évidentes. Par conséquent, la meilleure utilisation de ADD est l'extraction automatique du fichier tar local dans l'image, comme dans ADD rootfs.tar.xz /.

Si vous avez plusieurs étapes Dockerfile qui utilisent des fichiers différents de votre contexte, COPIEZ-les individuellement plutôt que tous en même temps. Cela garantira que le cache de construction de chaque étape n’est invalidé (ce qui oblige à réexécuter l’étape) si les fichiers spécifiquement requis changent.

Par exemple:

 COPY requirements.txt /tmp/
 RUN pip install --requirement /tmp/requirements.txt
 COPY . /tmp/

Cela entraîne moins d'invalidations de cache pour l'étape RUN que si vous mettez la commande COPY./tmp/avant.

Étant donné que la taille de l'image est importante, il est fortement déconseillé d'utiliser ADD pour récupérer des packages à partir d'URL distantes. vous devriez plutôt utiliser curl ou wget. De cette manière, vous pourrez supprimer les fichiers dont vous n’avez plus besoin une fois qu’ils ont été extraits, sans avoir à ajouter un autre calque à votre image. Par exemple, vous devriez éviter de faire des choses comme:

 ADD http://example.com/big.tar.xz /usr/src/things/
 RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
 RUN make -C /usr/src/things all

Et à la place, faites quelque chose comme:

 RUN mkdir -p /usr/src/things \
     && curl -SL htt,p://example.com/big.tar.xz \
     | tar -xJC /usr/src/things \
     && make -C /usr/src/things all

Pour les autres éléments (fichiers, répertoires) ne nécessitant pas la fonction d’extraction automatique de ADD, vous devez toujours utiliser COPY. "

13
jhpg

COPY copie un fichier/répertoire de votre hôte vers votre image.

ADD copie un fichier/répertoire de votre hôte vers votre image, mais peut également récupérer des URL distantes, extraire des fichiers TAR, etc.

Utilisez COPY pour copier simplement des fichiers et/ou des répertoires dans le contexte de construction.

Utilisez ADD pour télécharger des ressources distantes, extraire des fichiers TAR, etc.

9
JSON C11

COPIE

Ceci copie un ou plusieurs fichiers ou dossiers locaux dans la destination dans votre image Docker.

COPY < src> < dest >

COPY ["< source >",... "< destination >"] 

(ce formulaire est requis pour les chemins contenant des espaces)

Un exemple de fichier Docker qui utilise COPY Voici comment utiliser COPY dans un fichier Docker pour une application Ruby.

FROM Ruby:2.5.1
WORKDIR /usr/src/app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
CMD ["./your-daemon-or-script.rb"]

Il construit l'image en couches, en commençant par l'image parent Ruby: 2.5.1, définie à l'aide de FROM.

L'instruction Docker WORKDIR définit un répertoire de travail pour les instructions COPY ou ADD qui le suivent.

En copiant le Gemfiles suivi de RUN bundle install, un calque d'image est créé avec les gems Ruby installés, qui peuvent être mis en cache. Les deux dernières instructions de Docker copient les fichiers de l’application dans l’image et définissent la commande par défaut à l’aide de CMD.

Cela signifie que si vous modifiez l'un des fichiers de l'application, vous pouvez reconstruire l'image Docker à l'aide des couches parent et intermédiaire mises en cache. C'est beaucoup plus efficace que de tout construire à partir de zéro.

ADD

Cette instruction a la même syntaxe que COPY.

ADD < src> < dest >

ADD ["< source >",... "< destination >"] (this form is required for paths containing whitespace)

En plus de copier les fichiers et les répertoires locaux dans la destination dans l'image Docker, il comporte quelques fonctionnalités supplémentaires:

Si <source> est une archive tar locale dans un format de compression reconnu, elle est automatiquement décompressée en tant que répertoire dans l'image Docker. Par exemple: ADD rootfs.tar.xz /

Si <source> est une URL, le fichier sera téléchargé et copié dans la destination dans l'image Docker. Cependant, Docker déconseille d’utiliser ADD à cette fin.

Meilleure pratique de Dockerfile pour copier depuis une URL

Docker suggère qu'il est souvent inefficace de copier à partir d'une URL en utilisant ADD, et il est recommandé d'utiliser d'autres stratégies pour inclure les fichiers distants requis.

Étant donné que la taille de l'image est importante, il est fortement déconseillé d'utiliser ADD pour récupérer des packages à partir d'URL distantes. vous devriez plutôt utiliser curl ou wget. De cette façon, vous pourrez supprimer les fichiers dont vous n’avez plus besoin une fois qu’ils ont été extraits et vous n’aurez pas à ajouter un autre calque dans votre image. - Meilleures pratiques de Dockerfile

Par exemple, vous devriez éviter de faire des choses comme:

ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all

Et à la place, faites quelque chose comme:

RUN mkdir -p /usr/src/things \
    && curl -SL http://example.com/big.tar.xz \
    | tar -xJC /usr/src/things \
    && make -C /usr/src/things all

Pour les autres éléments (fichiers, répertoires) ne nécessitant pas la capacité d’extraction automatique de tar de ADD, vous devez toujours utiliser COPY.

5
Prakash

Source: https://nickjanetakis.com/blog/docker-tip-2-the-difference-between-copy-and-add-in-a-dockerile :

COPY et ADD sont deux instructions de Dockerfile ayant des objectifs similaires. Ils vous permettent de copier des fichiers d'un emplacement spécifique dans une image Docker.

COPY prend dans un src et une destination. Il vous permet uniquement de copier un fichier ou un répertoire local à partir de votre hôte (la machine créant l'image Docker) dans l'image Docker elle-même.

ADD vous permet de le faire aussi, mais il prend également en charge 2 autres sources. Tout d'abord, vous pouvez utiliser une URL au lieu d'un fichier/répertoire local. Deuxièmement, vous pouvez extraire un fichier tar de la source directement dans la destination.

Un cas d'utilisation valide pour ADD consiste à extraire un fichier tar local dans un répertoire spécifique de votre image Docker.

Si vous copiez des fichiers locaux sur votre image Docker, utilisez toujours COPY car elle est plus explicite.

4
Shagun Pruthi

Note importante

Je devais COPY et désarchiver Java le package dans mon image de menu fixe. Lorsque j'ai comparé la taille de l'image du menu fixe créée avec ADD, elle était 180 Mo plus grande que celle créée avec COPY, tar -xzf * .tar.gz et rm * .tar.gz.

Cela signifie que même si ADD supprime le fichier tar, il est toujours conservé quelque part. Et ça rend l'image plus grande !!

2
Avi Veltz

Depuis Docker 17.05, COPY est utilisé avec l'indicateur --from dans constructions à plusieurs étages pour copier les artefacts des étapes de construction précédentes dans l'étape de construction actuelle.

de la documentation

COPY accepte éventuellement un indicateur --from=<name|index> pouvant être utilisé pour définir l'emplacement source sur une étape de construction précédente (créée avec FROM .. AS) qui sera utilisée à la place du contexte de construction envoyé par l'utilisateur.

0
MCI
docker build -t {image name} -v {Host directory}:{temp build directory} .

C'est une autre façon de copier des fichiers dans une image. L'option -v crée temporairement un volume que nous avons utilisé lors du processus de construction.

Cela diffère des autres volumes car il monte un répertoire d'hôte pour la construction uniquement. Les fichiers peuvent être copiés à l'aide d'une commande cp standard.

De même, comme curl et wget, il peut être exécuté dans une pile de commandes (s'exécute dans un seul conteneur) sans multiplier la taille de l'image. ADD et COPY ne sont pas empilables, car ils s'exécutent dans un conteneur autonome et les commandes ultérieures sur les fichiers exécutés dans des conteneurs supplémentaires multiplient la taille de l'image:

Avec les options définies ainsi:

-v /opt/mysql-staging:/tvol

Ce qui suit sera exécuté dans un conteneur:

RUN cp -r /tvol/mysql-5.7.15-linux-glibc2.5-x86_64 /u1 && \
    mv /u1/mysql-5.7.15-linux-glibc2.5-x86_64 /u1/mysql && \

    mkdir /u1/mysql/mysql-files && \
    mkdir /u1/mysql/innodb && \
    mkdir /u1/mysql/innodb/libdata && \
    mkdir /u1/mysql/innodb/innologs && \
    mkdir /u1/mysql/tmp && \

    chmod 750 /u1/mysql/mysql-files && \
    chown -R mysql /u1/mysql && \
    chgrp -R mysql /u1/mysql
0
Dennis Payne