В чем разница между командами "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
в свой контейнер, но вместо этого вы распыляете содержимое на файловую систему.
Ответ 2
COPY
является
То же, что и "ADD", но без обработки tar и удаленного URL.
Ссылка прямо из исходного кода.
Ответ 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.