В чем разница между командами COPY и ADD в Dockerfile, и когда следует использовать одну вместо другой?
COPY
Инструкция COPY скопирует новые файлы из
ADD
Инструкция ADD скопирует новые файлы из
Команды COPY и ADD в Dockerfile оба копируют файлы с хоста в контейнер, но ADD имеет дополнительные функции, такие как автоматическая распаковка сжатых файлов и загрузка удаленных URL-адресов, в то время как COPY проще и более предсказуема. Вы должны предпочитать COPY для простого копирования файлов и использовать ADD только тогда, когда вам конкретно нужны его дополнительные функции, такие как распаковка архивов или загрузка удаленных файлов.
Содержание
- Базовые определения
- Ключевые различия
- Когда использовать COPY
- Когда использовать ADD
- Лучшие практики
- Примеры и варианты использования
- Рассмотрения производительности
Базовые определения
Инструкция COPY проста - она копирует файлы или каталоги из контекста сборки в файловую систему контейнера. Синтаксис прост: COPY <src> <dest>, где <src> может быть путем к файлу или каталогу, а <dest> - путем назначения в контейнере.
Инструкция ADD на поверхности выглядит похожей - ADD <src> <dest> - но включает дополнительную функциональность помимо простого копирования файлов. Хотя обе инструкции в конечном итоге помещают файлы в контейнер, ADD имеет специальную обработку для определенных типов файлов и источников.
Ключевые различия
Автоматическая распаковка файлов
ADD может автоматически распаковывать сжатые файлы, такие как .tar, .tar.gz, .tar.bz2, .tar.xz, .zip и .tgz при копировании в контейнер. COPY просто скопирует эти файлы как есть без распаковки.
# ADD автоматически распакует архив
ADD archive.tar.gz /path/to/extract/
# COPYING скопирует архив как единый файл
COPY archive.tar.gz /path/to/archive.tar.gz
Поддержка удаленных URL-адресов
ADD может загружать файлы с удаленных URL-адресов и помещать их в контейнер, в то время как COPY не может обрабатывать удаленные источники.
# 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 обрабатывает это автоматически.
# Использование 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.
Примеры и варианты использования
Простое копирование файла
# Лучшая практика - используйте COPY для простых файлов
COPY config.json /app/config/
COPY requirements.txt /app/
Распаковка архива
# Хороший вариант использования для ADD - распаковка архива
ADD source-code.tar.gz /app/source/
WORKDIR /app/source
Загрузка удаленного файла
# Только ADD может обрабатывать URL-адреса
ADD https://github.com/user/repo/archive/main.zip /tmp/repo.zip
RUN unzip /tmp/repo.zip -d /app/
Многоэтапные сборки
В многоэтапных сборках вы можете использовать ADD для копирования распакованных артефактов между этапами:
# Этап 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 только тогда, когда вам конкретно нужны его дополнительные функции
- Обе команды влияют на кэш сборки и размер образа
Практические рекомендации
- Начинайте с COPY для всех ваших потребностей в копировании файлов
- Переключайтесь на ADD только тогда, когда вам нужна распаковка архивов или загрузка удаленных URL-адресов
- Документируйте свое использование ADD, чтобы сделать поведение Dockerfile понятным
- Учитывайте компромисс между удобством и прозрачностью
- Тестируйте поведение вашего Dockerfile, чтобы оно соответствовало ожиданиям
Связанные вопросы
- Могу ли я использовать COPY и ADD в одном Dockerfile? Да, но в целом лучше стандартизировать на одной, когда это возможно
- Работает ли ADD со всеми форматами архивов? ADD поддерживает распространенные форматы, такие как .tar, .tar.gz, .zip и т.д.
- Устарел ли ADD? Нет, но для большинства случаев использования он менее рекомендуется, чем COPY