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>
.
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 URLADD
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.
COPY
est
Identique à 'ADD', mais sans la gestion des URL tar et distante.
Référence directement du code source .
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 utilisercurl
ouwget
à 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 utiliserCOPY
.
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 /.
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.
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. "
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.
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
.
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.
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 !!
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.
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