НейроАгент

COPY vs ADD в Dockerfile: Полное руководство

Узнайте ключевые различия между командами COPY и ADD в Dockerfile. Узнайте, когда использовать каждую команду для оптимальной сборки Docker-образов и лучших практик.

Вопрос

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

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

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

НейроАгент

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

Содержание

Базовые определения

Инструкция COPY проста - она копирует файлы или каталоги из контекста сборки в файловую систему контейнера. Синтаксис прост: COPY <src> <dest>, где <src> может быть путем к файлу или каталогу, а <dest> - путем назначения в контейнере.

Инструкция ADD на поверхности выглядит похожей - ADD <src> <dest> - но включает дополнительную функциональность помимо простого копирования файлов. Хотя обе инструкции в конечном итоге помещают файлы в контейнер, ADD имеет специальную обработку для определенных типов файлов и источников.


Ключевые различия

Автоматическая распаковка файлов

ADD может автоматически распаковывать сжатые файлы, такие как .tar, .tar.gz, .tar.bz2, .tar.xz, .zip и .tgz при копировании в контейнер. COPY просто скопирует эти файлы как есть без распаковки.

dockerfile
# ADD автоматически распакует архив
ADD archive.tar.gz /path/to/extract/

# COPYING скопирует архив как единый файл
COPY archive.tar.gz /path/to/archive.tar.gz

Поддержка удаленных URL-адресов

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

dockerfile
# ADD может загружать с URL-адресов
ADD http://example.com/file.zip /path/to/file.zip

# COPY не может обрабатывать URL-адреса - это приведет к ошибке
# COPY http://example.com/file.zip /path/to/file.zip

Поведение с каталогами

Обе команды обрабатывают каталоги похожим образом, но COPY более предсказуема при работе с содержимым каталогов. ADD имеет некоторые крайние случаи с обработкой каталогов, которые могут быть неожиданными.

Чувствительность к контексту сборки

COPY более строга в отношении контекста сборки - она позволяет копировать только из каталога контекста сборки или его подкаталогов. ADD более гибкая, но может привести к неожиданному поведению.


Когда использовать COPY

COPY должна быть вашим выбором по умолчанию для большинства операций копирования файлов в Dockerfile. Используйте COPY, когда:

  • Вам нужно простое, предсказуемое копирование файлов
  • Вы копируете файлы, которые НЕ должны быть распакованы (например, файлы конфигурации)
  • Вы хотите сохранить прозрачность в вашем Dockerfile
  • Вы копируете локальные файлы, которые не требуют специальной обработки
  • Вам нужно лучшее поведение кэширования сборки

COPY предпочтительна в сообществе Docker, потому что она более явная и имеет меньше скрытых поведений. Когда кто-то видит COPY в вашем Dockerfile, он точно знает, что происходит, не needing to understand additional rules.


Когда использовать ADD

ADD имеет конкретные варианты использования, где она предоставляет ценность по сравнению с COPY. Используйте ADD, когда:

  • Вам нужно автоматически распаковывать сжатые архивы
  • Вам нужно загружать файлы с удаленных URL-адресов во время сборки
  • Вы хотите уменьшить количество слоев в вашем Dockerfile
  • Вы работаете с устаревшими Dockerfile, которые уже эффективно используют ADD

Функция автоматической распаковки может быть особенно полезна для упрощения сложности Dockerfile. Вместо необходимости отдельных команд RUN для распаковки архивов, ADD обрабатывает это автоматически.

dockerfile
# Использование ADD для распаковки и уменьшения количества слоев
ADD application.tar.gz /app/
RUN cd /app && ./install.sh

# Альтернатива с COPY (больше слоев)
COPY application.tar.gz /tmp/
RUN tar -xzf /tmp/application.tar.gz -C /app/
RUN /app/install.sh

Лучшие практики

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

Официальная документация Docker и лучшие практики сообщества рекомендуют использовать COPY вместо ADD, когда это возможно. Поведение COPY более предсказуемо и прозрачно.

Используйте ADD с осторожностью

Используйте ADD только тогда, когда вам конкретно нужны его дополнительные функции. Избегайте использования ADD просто потому, что “это работает” - понимайте, почему вы выбираете его вместо COPY.

Комбинируйте с командами RUN

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

Учитывайте кэш сборки

Обе команды влияют на кэш сборки, но более простое поведение COPY иногда может привести к более предсказуемым шаблонам инвалидации кэша.

Будьте явны в отношении типов файлов

Если вы используете ADD для автоматической распаковки, укажите это в комментариях, так как это поведение не очевидно для всех пользователей Docker.


Примеры и варианты использования

Простое копирование файла

dockerfile
# Лучшая практика - используйте COPY для простых файлов
COPY config.json /app/config/
COPY requirements.txt /app/

Распаковка архива

dockerfile
# Хороший вариант использования для ADD - распаковка архива
ADD source-code.tar.gz /app/source/
WORKDIR /app/source

Загрузка удаленного файла

dockerfile
# Только ADD может обрабатывать URL-адреса
ADD https://github.com/user/repo/archive/main.zip /tmp/repo.zip
RUN unzip /tmp/repo.zip -d /app/

Многоэтапные сборки

В многоэтапных сборках вы можете использовать ADD для копирования распакованных артефактов между этапами:

dockerfile
# Этап 1: Сборка с ADD для распаковки
FROM builder as build
ADD source.tar.gz /build/
RUN cd /build && make build

# Этап 2: Копируйте только то, что нужно
FROM runtime
COPY --from=build /build/artifact /app/bin/

Рассмотрения производительности

Влияние на время сборки

Автоматическая распаковка ADD иногда может быть быстрее, чем отдельные команды COPY + RUN tar, но разница часто незначительна. Основное внимание следует уделять читаемости и поддерживаемости.

Размер образа

Обе команды способствуют итоговому размеру образа, но автоматическая распаковка ADD не создает inherently меньшие образы, чем ручная распаковка с командами COPY + RUN.

Эффективность кэширования

Более простое поведение COPY может привести к более предсказуемым попаданиям в кэш. Когда вы изменяете файл, который использует COPY, Docker точно знает, что изменилось. Дополнительная сложность ADD иногда может привести к неожиданному поведению кэширования.


Заключение

Ключевые выводы

  • COPY проще и более предсказуема - используйте ее как выбор по умолчанию
  • ADD имеет специальные функции для распаковки архивов и загрузки удаленных URL-адресов
  • Предпочитайте COPY для прозрачности и явного поведения
  • Используйте ADD только тогда, когда вам конкретно нужны его дополнительные функции
  • Обе команды влияют на кэш сборки и размер образа

Практические рекомендации

  1. Начинайте с COPY для всех ваших потребностей в копировании файлов
  2. Переключайтесь на ADD только тогда, когда вам нужна распаковка архивов или загрузка удаленных URL-адресов
  3. Документируйте свое использование ADD, чтобы сделать поведение Dockerfile понятным
  4. Учитывайте компромисс между удобством и прозрачностью
  5. Тестируйте поведение вашего Dockerfile, чтобы оно соответствовало ожиданиям

Связанные вопросы

  • Могу ли я использовать COPY и ADD в одном Dockerfile? Да, но в целом лучше стандартизировать на одной, когда это возможно
  • Работает ли ADD со всеми форматами архивов? ADD поддерживает распространенные форматы, такие как .tar, .tar.gz, .zip и т.д.
  • Устарел ли ADD? Нет, но для большинства случаев использования он менее рекомендуется, чем COPY

Источники

  1. Официальная документация Docker - Инструкции Dockerfile
  2. Лучшие практики Docker - Используйте COPY вместо ADD
  3. ADD vs COPY в Dockerfile - Stack Overflow
  4. Справочник Dockerfile - Инструкция ADD
  5. Лучшие практики Docker - Управление данными приложения