В чем разница между COPY и ADD в Docker?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между инструкциями COPY и ADD в Docker
Обе инструкции COPY и ADD используются в Dockerfile для копирования файлов и директорий из хост-системы в образ контейнера, но они имеют существенные различия в функциональности и рекомендуемом использовании.
Основные различия
Инструкция COPY
COPY — это базовая инструкция, которая выполняет прямую задачу: копирует файлы и директории из локальной файловой системы (контекста сборки) в файловую систему образа.
Синтаксис:
COPY [--chown=<user>:<group>] <src>... <dest>
Ключевые особенности:
- Копирует только локальные файлы из контекста сборки Docker
- Не поддерживает автоматическую распаковку архивов
- Не поддерживает загрузку файлов из URL
- Более предсказуема и явна в поведении
- Рекомендуется для большинства случаев согласно best practices Docker
Пример использования:
COPY package.json /app/
COPY ./src /app/src
COPY --chown=node:node config/ /app/config/
Инструкция ADD
ADD — более функциональная инструкция с дополнительными возможностями, но менее предсказуемая.
Синтаксис:
ADD [--chown=<user>:<group>] <src>... <dest>
Дополнительные возможности ADD:
- Автоматическая распаковка архивов (tar, gzip, bzip2, xz)
- Поддержка URL в качестве источника (скачивание файлов из интернета)
- Поддержка тех же операций, что и
COPY
Пример использования ADD:
ADD https://example.com/file.tar.gz /tmp/
ADD application.tar.gz /app/
ADD --chown=user:group ./data.tar.xz /data/
Подробное сравнение
Работа с архивами
COPY: Требует явной распаковки архива
COPY archive.tar.gz /tmp/
RUN tar -xzf /tmp/archive.tar.gz -C /app && \
rm /tmp/archive.tar.gz
ADD: Автоматически распаковывает архивы
ADD archive.tar.gz /app/
# Архив автоматически распаковывается в /app/
Загрузка из URL
COPY: Не поддерживает URL — вызывает ошибку сборки
# Так не сработает:
COPY https://example.com/file.txt /app/
ADD: Поддерживает загрузку из URL
ADD https://example.com/file.txt /app/
# Файл будет загружен из интернета
Рекомендации и best practices
Когда использовать COPY (рекомендуется в 95% случаев):
- Для копирования локальных файлов и директорий
- Когда нужна явность и предсказуемость
- Для соблюдения принципа минимальной достаточности
- В production-сборках для повышения безопасности
Когда можно использовать ADD:
- Для автоматической распаковки локальных архивов
ADD application.tar.gz /app/ - Для загрузки файлов из URL (хотя лучше использовать
RUN wgetилиRUN curlдля большей контролируемости)ADD https://go.dev/dl/go1.21.0.linux-amd64.tar.gz /tmp/
Важные предупреждения
Проблемы безопасности ADD:
# Потенциально опасно - скачивание из непроверенного источника
ADD https://untrusted-source.com/script.sh /app/
Непредсказуемое поведение:
ADD file.tar.gz /app/
# Если file.tar.gz - не архив, а обычный файл с таким расширением,
# он будет скопирован без распаковки
Практический пример сравнения
Вариант с COPY (рекомендуемый):
FROM alpine:latest
# Копируем локальные файлы
COPY package.json /app/
COPY src/ /app/src/
# Явная распаковка архива
COPY dependencies.tar.gz /tmp/
RUN tar -xzf /tmp/dependencies.tar.gz -C /app && \
rm /tmp/dependencies.tar.gz
# Явная загрузка из URL
RUN wget -O /app/datafile.json https://example.com/data.json
Вариант с ADD:
FROM alpine:latest
ADD package.json /app/
ADD src/ /app/src/
ADD dependencies.tar.gz /app/ # Автоматическая распаковка
ADD https://example.com/data.json /app/datafile.json
Выводы
- Используйте
COPYпо умолчанию — это явная, безопасная и предсказуемая инструкция - Используйте
ADDтолько когда нужны его специфические функции (распаковка архивов или загрузка из URL) - Для загрузки из URL лучше использовать
RUNсcurl/wget— это дает больше контроля над процессом - Явность лучше магии — явная распаковка архивов понятнее, чем автоматическая
Основное правило: если вам не нужны специальные возможности ADD, всегда выбирайте COPY — это делает Dockerfile более читаемым, безопасным и соответствующим best practices индустрии.