Яка різниця між командами 'КОПІРУВАННЯ' та 'ДОБАВЛЕННЯ' в Dockerfile?


2196

Яка різниця між командами COPYта ADDкомандами в Dockerfile, і коли я буду використовувати одну над іншою?

COPY <src> <dest>

Інструкція COPY скопіює нові файли з <src>та додасть їх у файлову систему контейнера на шляху<dest>

ADD <src> <dest>

Інструкція ADD буде копіювати нові файли з них <src>та додавати їх до файлової системи контейнера на шляху <dest>.


11
Перегляньте найкращі практики: docs.docker.com/engine/userguide/eng-image/…
EricSonaron

9
Станом на червень 2018 року в посиланні говориться, що ADD додає до зображення (тобто статичний файл), тоді як COPY додає до контейнера (тобто екземпляр часу виконання зображення). Звичайно, це означає, що COPY виконується щоразу, коли зображення запущено Docker, або, можливо, це просто випадок суперечливої ​​термінології?
Кріс Робінсон

14
Я думаю, що це суперечлива термінологія
Даніель Стівенс

6
@ChrisRobinson, виконувати це буде неможливо COPYкожен раз, коли він запускається, оскільки він не обов'язково має доступ до оригінального контексту, щоб захопити вміст.
Кен Вільямс

Відповіді:


2166

Ви повинні перевірити ADDта COPYдокументацію для більш детального опису їх поведінки, але в двох словах, головна різниця полягає в тому, що ADDможна зробити більше, ніж COPY:

  • ADDдозволяє <src>бути URL-адресою
  • Посилаючись на коментарі нижче, у ADD документації зазначено, що:

    Якщо локальний архів tar у розпізнаному форматі стиснення (ідентифікація, gzip, bzip2 або xz), він розпаковується як каталог. Ресурси з віддалених URL-адрес не декомпресуються.

Зауважте, що кращі практики написання Dockerfiles пропонують використовувати COPYтам, де магія ADDне потрібна. В іншому випадку ви ( оскільки вам довелося шукати цю відповідь ), ймовірно, ви здивуєтесь колись, коли маєте намір скопіювати keep_this_archive_intact.tar.gzу свій контейнер, але натомість ви розпорошите вміст на вашу файлову систему.


65
Просто хотів щось уточнити: використання ADD з URL-адресою до .tar.gz НЕ ЕКСТРУЮТЬ архів у файлову систему (я двічі перевірив зараз, щоб бути впевненим, і це підтверджено)
Cecile

42
Це важлива інформація, і це злочин, який в офіційній довідці Dockerfile таким чином не з'ясовує різницю.
Сисо

1
Не впевнений, якщо це відрізняється від зображення до зображення. Я використовував зображення для завантаження і додавання для zip-файлу. Він просто з’явився в каталозі призначення, не розгортаючи його. Я припускаю, що видобуток відбувається лише для тарболу, але я цього не перевіряв.
Сантош Кумар Арджунан

4
@SantoshKumarArjunan: Докерські документи вказують наступне про ДОБАВЛЕННЯ та автоматичне видобування дьогтю: If <src> is a local tar archive in a recognized compression format (identity, gzip, bzip2 or xz) then it is unpacked as a directory. Resources from remote URLs are not decompressed. Docker ADD
hmacias

1
COPY дозволяє --from = <ім'я | індекс>, де я не можу знайти таку ж підтримку для ADD
Брендон

474

COPY є

Те саме, що "ADD", але без дьогтю та віддаленої обробки URL-адрес.

Посилання прямо з вихідного коду .


15
Чи правильно це я бачу: ADDтакож створює неіснуючі каталоги . Тож, хоч якось не відволікається у цій цілій нитці, вона має перевагу над COPYтим, що вам не доведеться бігати mkdirі зберігати деякі набравши тексту
eli

3
COPY робить це теж @eli
bhordupur

Найкраще пояснення поки що. Чому це не прийнята відповідь?
xdevx32

141

На цю тему існує офіційна документація: Кращі практики написання докерфілів

Оскільки розмір зображення має значення, використання ADDдля отримання пакетів з віддалених URL-адрес сильно не рекомендується; ви повинні використовувати curlабо wgetзамість цього. Таким чином ви можете видалити файли, які вам більше не потрібні після їх вилучення, і вам не доведеться додавати ще один шар у зображення.

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

Для інших елементів (файлів, каталогів), які не потребують ADDможливості автоматичного вилучення дьогтю, завжди слід використовувати COPY.


2
Дивіться також цю комісію
michielbdejong

18
Докер каже, що віддавати перевагу COPY, тому що це прозоріше. Із найкращих практик Докер-файлу (2014-12-15): Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. That’s because it’s more transparent than ADD. COPY only supports the basic copying of local files into the container, while ADD has some features that are not immediately obvious.
схема

115

З Докерів Docs:

ДОДАТИ або КОПІЮЙТЕ

Хоча ADD і COPY функціонально схожі, загалом кажучи, COPY є кращим. Це тому, що вона прозоріша, ніж додавання. COPY підтримує лише основне копіювання локальних файлів у контейнер, тоді як ADD має деякі функції (наприклад, лише видобуток смоли та підтримка віддаленої URL-адреси), які не відразу очевидні. Отже, найкращим використанням для ADD є локальне автоматичне вилучення файлу tar на зображення, як у ADD rootfs.tar.xz /.

Докладніше: Кращі практики написання Dockerfiles


46

Якщо ви хочете додати xx.tar.gz до /usr/localконтейнера, розпакуйте його та видаліть непотрібний стислий пакет.

Для КОПІЇ:

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

ДОДАТИ:

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

ADD підтримує видобуток лише смоли. Крім цього, COPY використовуватиме три шари, але ADD використовує лише один шар.


3
Будь-яка причина, чому не просто два шари? RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local && rm /tmp/jdk-7u79-linux-x64.tar.gz
Стівен С

25

COPY копіює файл / каталог з вашого хоста на ваше зображення.

ADD копіює файл / каталог з вашого хоста на ваше зображення, але також може отримати віддалені URL-адреси, витягувати файли TAR тощо.

Використовуйте COPYдля простого копіювання файлів та / або каталогів у контекст збірки.

Використовується ADDдля завантаження віддалених ресурсів, вилучення файлів TAR тощо.


5
ідеальне пояснення для
нооба,

17

З Докерів Документів: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy

"Хоча ADD і COPY функціонально схожі, загалом кажучи, COPY є кращим. Це тому, що це прозоріше, ніж ADD. COPY підтримує лише основне копіювання локальних файлів у контейнер, тоді як ADD має деякі особливості (наприклад, видобуток лише місцевих смол та підтримка віддаленої URL-адреси), які не відразу очевидні, отже, найкращим використанням для ADD є локальне автоматичне вилучення файлу tar на зображення, як у ADD rootfs.tar.xz /.

Якщо у вас є кілька кроків Dockerfile, які використовують різні файли з вашого контексту, КОПУЙТЕ їх окремо, а не всі відразу. Це забезпечить, що кеш збірки кожного кроку буде недійсним (змушує повторно виконувати крок), якщо зміниться спеціально необхідні файли.

Наприклад:

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

Результати мають меншу кількість недійсних кеш-пам’яті для кроку RUN, ніж якщо ви ставите КОПІЮВАННЯ. / tmp / перед цим.

Оскільки розмір зображення має значення, використання ADD для отримання пакетів з віддалених URL-адрес сильно не рекомендується; ви повинні використовувати замість curl або wget. Таким чином ви можете видалити файли, які вам більше не потрібні після їх вилучення, і вам не доведеться додавати ще один шар у зображення. Наприклад, вам слід уникати таких дій, як:

 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

А натомість зробіть щось на кшталт:

 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

Для інших елементів (файлів, каталогів), які не потребують можливості автоматичного вилучення ADD tar, завжди слід використовувати COPY. "


7

Джерело: https://nickjanetakis.com/blog/docker-tip-2-the-difference-between-copy-and-add-in-a-dockerile :

COPY і ADD - це інструкції Dockerfile, які служать подібним цілям. Вони дозволяють вам копіювати файли з певного місця в зображення Docker.

COPY приймає в src та пункт призначення. Це дозволяє лише скопіювати локальний файл або каталог зі свого хоста (машина, що будує зображення Docker), у сам Docker-образ.

ADD дозволяє зробити це теж, але він також підтримує 2 інших джерела. По-перше, ви можете використовувати URL, а не локальний файл / каталог. По-друге, ви можете витягнути файл tar з джерела безпосередньо в пункт призначення

Дійсний випадок використання ADD - це коли потрібно витягнути локальний файл tar в певний каталог вашого зображення Docker.

Якщо ви копіюєте в локальні файли на зображення Docker, завжди використовуйте COPY, оскільки це більш явно.


7

Під час створення Dockerfile є дві команди, які можна використовувати для копіювання файлів / каталогів у нього - ADDі COPY. Хоча є незначні відмінності в обсязі їх функції, вони по суті виконують одне і те ж завдання.

Отже, чому у нас є дві команди, і як ми знаємо, коли використовувати ту чи іншу?

DOCKER ADDCOMMAND

Почнемо з того, що ADDкоманда старша за COPY. З моменту запуску платформи Docker ADDінструкція входила до її списку команд.

Команда копіює файли / каталоги у файлову систему вказаного контейнера.

Основний синтаксис ADDкоманди:

ADD <src> … <dest>

Він включає джерело, яке ви хочете скопіювати ( <src>), а потім місце призначення, де ви хочете його зберегти ( <dest>). Якщо джерелом є каталог, ADDскопіюйте все, що знаходиться всередині нього (включаючи метадані файлової системи).

Наприклад, якщо файл локально доступний і ви хочете додати його до каталогу зображення, ви вводите:

ADD /source/file/path  /destination/path

ADDтакож можна копіювати файли з URL-адреси. Він може завантажити зовнішній файл і скопіювати його до потрібного пункту призначення. Наприклад:

ADD http://source.file/url  /destination/path

Додатковою особливістю є те, що вона копіює стиснуті файли, автоматично витягуючи вміст у вказане призначення. Ця функція стосується лише локально збережених стислих файлів / каталогів.

ADD source.file.tar.gz /temp

Майте на увазі, що ви не можете завантажити та витягнути стислий файл / каталог з URL-адреси. Команда не розпаковує зовнішні пакети при копіюванні їх у локальну файлову систему.

DOCKER COPYCOMMAND

Через деякі проблеми з функціональністю, Докер повинен був ввести додаткову команду для дублювання вмісту - COPY.

На відміну від тісно пов'язаної ADDкоманди, COPYмає лише одну призначену функцію. Його роль полягає у копіюванні файлів / каталогів у визначеному місці у їх наявному форматі. Це означає, що він не займається вилученням стислого файлу, а скопіює його як є.

Інструкцію можна використовувати лише для локально збережених файлів. Тому ви не можете використовувати його з URL-адресами для копіювання зовнішніх файлів у ваш контейнер.

Щоб використовувати COPYінструкцію, дотримуйтесь основного формату команд:

Введіть джерело і де ви хочете, щоб команда витягувала вміст наступним чином:

COPY <src> … <dest> 

Наприклад:

COPY /source/file/path  /destination/path 

Яку команду використовувати? (Найкраща практика)

З огляду на обставини, за яких COPYкоманда була введена, очевидно, що зберігання ADDбуло необхідним. Docker опублікував офіційний документ, в якому викладені кращі практики написання Dockerfiles, який прямо не рекомендує використовувати ADDкоманду.

В офіційній документації Докера зазначається, що COPYзавжди слід використовувати інструкцію, оскільки вона є більш прозорою, ніж ADD.

Якщо вам потрібно скопіювати з контексту локальної збірки в контейнер, дотримуйтесь використання COPY.

Команда Docker також сильно відмовляє ADDвід завантаження та копіювання пакету з URL-адреси. Натомість безпечніше та ефективніше використовувати wget чи curl у межах RUNкоманди. Тим самим ви уникаєте створення додаткового шару зображення та заощаджуєте простір.


4

Важлива примітка

Мені довелося COPYзнімати пакет java в моєму докерському образі. Коли я порівнював розмір зображення докера, створеного за допомогою ADD, він був на 180 Мб більший за розмір, створений за допомогою COPY, tar -xzf * .tar.gz та rm * .tar.gz

Це означає, що хоч ADD видаляє файл tar, він все ще зберігається десь. І це робить зображення більшим !!


Чи все-таки це стосується останньої версії Docker?
Навін

3

Оскільки Docker 17.05 COPYвикористовується з --fromпрапором у багатоетапних складах для копіювання артефактів з попередніх етапів збірки на поточну стадію збірки.

з документації

За бажанням COPY приймає прапор, --from=<name|index>який може бути використаний для встановлення місця розташування джерела на попередньому етапі збірки (створеному з FROM .. AS), який буде використовуватися замість контексту збірки, надісланого користувачем.


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

Це ще один спосіб копіювання файлів у зображення. Параметр -v тимчасово створює об'єм, який ми використовували під час збирання.

Це відрізняється від інших томів, оскільки він монтує хост-каталог лише для збірки. Файли можна скопіювати за допомогою стандартної команди cp.

Крім того, як curl і wget, він може бути запущений у командному стеку (працює в одному контейнері) і не примножувати розмір зображення. ADD і COPY не підлягають складенню, оскільки вони працюють у окремому контейнері, і наступні команди на тих файлах, які виконуються в додаткових контейнерах, збільшать розмір зображення:

Завдяки таким параметрам:

-v /opt/mysql-staging:/tvol

У одному контейнері буде виконано наступне:

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

1
На якій версії докера ви бачите цю опцію? Це не документально підтверджено та не працює на моєму клієнті 1.12.1.
BMitch

2
Насправді ця функція досі не була включена в основний реліз, і все ще багато дискусій на цю тему, тому ми не повинні її очікувати давно ... Дивіться звіт про помилки для отримання додаткової інформації: github.com/ докер / докер / випуски / 14080 .
jwatkins

1
Так, такої опції немає (перевірено в останній версії 17.06). Ця відповідь вводить в оману. unknown shorthand flag: 'v' in -v
Кірбі

Оманливий коментар справді
Гідо ван Стін

Том Docker тут не мав нічого робити у відповіді, будь ласка, якщо ви можете, відповісти на пряме запитання :), це легко відповідь.
Маджід Алі Хан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.