Чем отличает COPY от ADD
Инструкции COPY и ADD используются в Dockerfile для копирования файлов и директорий из файловой системы хоста в файловую систему контейнера. Несмотря на то, что обе команды на первый взгляд выполняют схожие задачи, между ними есть важные различия, которые влияют на поведение контейнеров и читаемость Dockerfile.
📌 Общие черты
- Обе инструкции копируют файлы из контекста сборки (обычно папка рядом с Dockerfile).
Синтаксис одинаковый:
<br/>COPY <src> <dest>
ADD <src> <dest>
-
где:
-
<src> — путь к файлу или папке на хосте;
-
<dest> — путь внутри контейнера.
-
-
Обе команды создают новый слой образа, который можно кэшировать.
-
Обе инструкции не выполняют shell-команды (в отличие от RUN).
📌 Отличия между COPY и ADD
Возможность | COPY | ADD |
---|---|---|
Простое копирование | ✅ | ✅ |
--- | --- | --- |
Автоматическое извлечение архива | ❌ | ✅ (только .tar, .tar.gz, .tgz, .tar.bz2) |
--- | --- | --- |
Копирование из URL | ❌ | ✅ |
--- | --- | --- |
Поддержка только локальных файлов | ✅ | ✅ |
--- | --- | --- |
Явное поведение | ✅ | ❌ |
--- | --- | --- |
1. Копирование файлов и папок
-
COPY просто копирует указанный файл или каталог как есть.
-
ADD также копирует, но дополнительно может:
-
Распаковать архив;
-
Скачать файл по URL.
-
Пример:
COPY app/ /app/
ADD app/ /app/
Оба скопируют папку app/ в образ.
2. Распаковка архивов
-
ADD умеет распаковывать архивы .tar, .tar.gz и т.п. при копировании.
-
COPY — нет, он просто копирует архив как файл.
Пример:
ADD archive.tar.gz /app/
→ Контейнер получит распакованные файлы в /app/.
3. Копирование по URL
-
ADD может загружать файлы по HTTP(S).
-
COPY не поддерживает работу с удалёнными источниками.
Пример:
ADD https://example.com/config.json /config/
→ Скачивает файл и помещает в /config/.
4. Поведение с архивами: опасность неожиданностей
Если вы используете ADD и у вас есть файл .tar.gz, он будет автоматически распакован — иногда это может быть нежелательно. Это одна из причин, почему COPY чаще рекомендуется для предсказуемости.
🧠 Рекомендации по использованию
-
Используй COPY по умолчанию, когда нужно просто копировать файлы/папки.
-
Применяй ADD только при необходимости:
-
Автораспаковки .tar.* архивов;
-
Загрузки по URL.
-
🔒 Безопасность
-
Использование ADD для скачивания по URL может привести к уязвимостям (например, при подмене URL).
-
Поэтому при скачивании лучше использовать:
RUN curl -o file.ext https://example.com/file.ext
Это позволит явно указать, что происходит, и обработать ошибки.
🎯 Примеры
Копирование локального файла
COPY requirements.txt /app/
Распаковка архива
ADD code.tar.gz /app/
→ Распакует code.tar.gz в /app/.
Загрузка по URL
ADD https://example.com/file.tar.gz /tmp/
→ Скачает и (если это архив) распакует файл в /tmp/.
📍 Поведение с путями
-
Если src — каталог, а dest заканчивается на /, содержимое каталога копируется в эту директорию.
-
Если dest — не существует и не заканчивается на /, будет создан файл с именем dest.
🔧 Поддержка wildcards
- Подстановочные знаки (*, ?) поддерживаются в обоих, если указан COPY/ADD в форме списка:
COPY \["\*.txt", "/app/"\]
💡 Проверка на существование
Если файл или папка, указанные в COPY или ADD, не существуют в контексте сборки, сборка прерывается с ошибкой.
Таким образом, хотя COPY и ADD похожи, они предназначены для разных задач: COPY — для предсказуемого и безопасного копирования, ADD — для продвинутых случаев (распаковка и загрузка).