В чем разница между командами "COPY" и "ADD" в Dockerfile?

В чем разница между командами COPY и ADD в Dockerfile и когда я буду использовать одну поверх другой?

COPY <src> <dest>

Инструкция COPY скопирует новые файлы из <src> и добавит их в файловую систему контейнера по пути <dest>

ADD <src> <dest>

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

Ответы

Ответ 1

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

  • ADD позволяет <src> быть URL-адресом
  • Ссылаясь на комментарии ниже, в ADD документации четко говорится, что:

    Если это локальный архив tar в распознанном формате сжатия (identity, gzip, bzip2 или xz), то он распаковывается как каталог. Ресурсы с удаленных URL не распаковываются.

Обратите внимание, что Рекомендации по написанию Dockerfiles предлагают использовать COPY, где магия ADD не требуется. В противном случае вы (поскольку вам пришлось искать этот ответ), скорее всего, однажды удивитесь, когда захотите скопировать keep_this_archive_intact.tar.gz в свой контейнер, но вместо этого вы распыляете содержимое на файловую систему.

Ответ 3

В этой связи есть официальная документация: Рекомендации по написанию файлов докеров

Поскольку размер изображения имеет значение, использование 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

Для других элементов (файлов, каталогов), которые не требуют возможности автоматического извлечения t20 > s tar, вы всегда должны использовать COPY.

Ответ 4

Из документов Docker:

ДОБАВИТЬ или КОПИРОВАТЬ

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

Подробнее: Рекомендации по написанию файлов Dockerfiles

Ответ 5

Если вы хотите добавить 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:

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

ADD поддерживает локальное извлечение tar. Помимо этого, COPY будет использовать три слоя, но ADD использует только один слой.

Ответ 6

Из документов Docker: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy

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

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

Например:

 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

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

Ответ 7

COPY копирует файл/каталог с вашего хоста на ваше изображение.

ADD копирует файл/каталог с вашего хоста в ваше изображение, но также может извлекать удаленные URL, извлекать файлы TAR и т.д.

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

Используйте ADD для загрузки удаленных ресурсов, извлечения файлов TAR и т.д.

Ответ 8

COPY будет работать в большинстве случаев.

ADD имеет все возможности COPY и имеет следующие дополнительные функции:

Разрешает автоматическое извлечение tar файла на изображении, например

ADD app.tar.gz /opt/var/myapp.

Позволяет загружать файлы с удаленного URL-адреса. Однако загруженные файлы станут частью изображения. Это приводит к раздуванию изображения. Таким образом, рекомендуется использовать cURL или Wget, чтобы загрузить архив в явном виде, извлечь и удалить архив.

Ответ 9

Источник: 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, потому что это более явно.

Ответ 10

Важная заметка

Мне пришлось COPY и распаковать Java-пакет в моем образе докера. Когда я сравнил размер образа докера, созданного с помощью ADD, он был на 180 МБ больше, чем размер изображения, созданного с помощью COPY, tar -xzf *.tar.gz и rm *.tar.gz.

Это означает, что хотя ADD удаляет файл tar, он все равно где-то хранится. И это делает изображение больше!

Ответ 11

Поскольку Docker 17.05 COPY используется с флагом --from в многоэтапных сборках для копирования артефактов с предыдущих этапов сборки на текущий этап сборки.

из документации

При желании COPY принимает флаг --from=<name|index>, который можно использовать для установки исходного местоположения на предыдущий этап сборки (созданный с помощью FROM.. AS), который будет использоваться вместо контекста сборки, отправленного пользователем.

Ответ 12

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

Ответ 13

COPY

Это копирует один или несколько локальных файлов или папок в место назначения в вашем образе Docker.

COPY

COPY ["" ""] (эта форма необходима для путей, содержащих пробелы)

Пример Dockerfile, который использует COPY. Так вы бы использовали COPY в Dockerfile для приложения на Ruby.

FROM ruby: 2.5.1 WORKDIR/usr/src/app COPY Gemfile Gemfile.lock./RUN комплект поставки установить COPY. , CMD ["./your-daemon-or-script.rb"]

Он строит изображение в слоях, начиная с родительского изображения ruby: 2.5.1, определенного с помощью FROM.

Инструкция Docker WORKDIR определяет рабочий каталог для инструкций COPY или ADD, которые следуют за ней.

Копируя Gemfiles с последующей установкой пакета RUN, создается слой образа с установленными Ruby Gems, который можно кэшировать. Последние две инструкции Docker копируют файлы приложений в образ и устанавливают команду по умолчанию с помощью CMD.

Это означает, что если вы измените какой-либо из файлов приложений, вы можете перестроить образ Docker, используя кэшированный родительский и промежуточный слои. Это гораздо эффективнее, чем создавать их все с нуля.

ДОБАВЛЯТЬ

Эта инструкция имеет синтаксис, аналогичный COPY.

ДОБАВЛЯТЬ

ADD ["" ""] (эта форма необходима для путей, содержащих пробелы)

Помимо копирования локальных файлов и каталогов в место назначения в образе Docker, у него есть некоторые дополнительные функции:

Если это локальный архив tar в распознанном формате сжатия, то он автоматически распаковывается в виде каталога в образ Docker. Например: ДОБАВИТЬ rootfs.tar.xz/

Если это URL, он загрузит и скопирует файл в место назначения в образе Docker. Однако Docker не рекомендует использовать ADD для этой цели.

Рекомендации по Dockerfile для копирования с URL

Докер предполагает, что зачастую неэффективно копировать URL-адрес с помощью ADD, и рекомендуется использовать другие стратегии для включения необходимых удаленных файлов.

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

Например, вы должны избегать таких вещей, как:

ДОБАВИТЬ http://example.com/big.tar.xz/usr/src/things/RUN tar -xJf/usr/src/things/big.tar.xz -C/usr/src/things RUN make [ CN01]/usr/src/things all И вместо этого сделайте что-то вроде:

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 Для других элементов (файлов, каталогов), для которых не требуется возможность автоматического извлечения tar из ADD, всегда следует использовать COPY.