Ответ
Обе инструкции копируют файлы и директории из контекста сборки в образ, но ADD обладает дополнительными, часто избыточными, возможностями.
COPY <src>... <dest>
- Копирует локальные файлы/директории из
<src>(относительно контекста сборки) в<dest>внутри образа. - Рекомендуется использовать по умолчанию для простого копирования, так как его поведение предсказуемо и прозрачно.
COPY ./package.json ./app.py /usr/src/app/ COPY ./configs/ /etc/app/
ADD <src>... <dest>
- Делает всё то же, что и
COPY, плюс две специфические функции:- Автоматическая распаковка локальных tar-архивов (
.tar,.tar.gz,.tar.bz2и т.д.) в пункте назначения.ADD ./application.tar.gz /opt/ # Содержимое архива будет распаковано в /opt/ - Поддержка URL в качестве
<src>. Docker скачает файл по ссылке и поместит его в образ.ADD https://example.com/downloads/tool.tar.gz /tmp/
- Автоматическая распаковка локальных tar-архивов (
Практическое правило: Используйте COPY для простого копирования файлов вашего приложения. ADD стоит применять только тогда, когда вам действительно нужна его уникальная функциональность — например, для распаковки локального архива зависимостей. Избегайте ADD для скачивания файлов из сети, так как это делает образ зависимым от внешнего ресурса и усложняет кэширование; лучше выполнить скачивание явно с помощью RUN curl или RUN wget.
Ответ 18+ 🔞
Слушай, давай разжую эту тему про COPY и ADD, а то народ путается, как последний дурак в аэропорту. Всё проще, чем кажется, если не лезть в дебри.
Представь, что COPY — это такой прямолинейный работяга. Ему дали файлы — он их тупо перенёс из точки А в точку Б внутри образа. Никаких фокусов, всё честно и прозрачно. Вот смотри:
COPY ./package.json ./app.py /usr/src/app/
COPY ./configs/ /etc/app/
Взял package.json, app.py и всю папку configs — и перетащил куда сказали. Ёпта, это твой основной инструмент. Используй его всегда, когда просто нужно скопировать свои файлы. Доверия к нему — ебать, стопроцентное, потому что он нихуя лишнего не делает.
А теперь ADD — это тот же работяга, но после трёх банок энергетика. Он тоже умеет копировать, но у него в запасе два особых, ебаньких, трюка.
Трюк первый: волшебная распаковка. Подсовываешь ему локальный .tar.gz архив — а он, хитрая жопа, не просто копирует этот комок файлов, а распаковывает его прямо на месте!
ADD ./application.tar.gz /opt/ # Он тут сам всё развернёт в /opt/, как по маслу
Удобно? Иногда — да, овердохуища. Но если ты не ждал этого фокуса, можно охуеть с неожиданности.
Трюк второй: интернет-зависимость. Можешь написать ему URL вместо пути.
ADD https://example.com/downloads/tool.tar.gz /tmp/
И он сам сходит в сеть, скачает этот файл и засунет в образ. Звучит заманчиво, но это, блядь, пиздопроебибна идея. Почему? Потому что твой образ становится заложником какого-то левого сайта. Упал сайт — сломался билд. Поменяли файл — инвалидировалось кэширование, и теперь каждый раз качается заново. Терпения ноль, ебать!
Поэтому золотое правило, чувак:
Хочешь просто скопировать свои файлы — юзай COPY. Всё. Предсказуемо, надёжно, без сюрпризов.
Хочешь распаковать архив — тогда можно ADD. Это его законная фича.
Хочешь что-то скачать из интернета — НЕ используй ADD. Вместо этого сделай всё явно и понятно через RUN:
RUN curl -fsSL https://example.com/tool.tar.gz -o /tmp/tool.tar.gz
&& tar -xzf /tmp/tool.tar.gz -C /opt/
&& rm /tmp/tool.tar.gz
Так ты контролируешь каждый шаг, и любой, кто посмотрит на твой Dockerfile, сразу поймёт, что тут происходит. А не будет гадать, какой хуй в пальто на этот раз выкинет инструкция ADD.
Короче, ADD — как опасная игрушка. Можно пользоваться, но только если точно знаешь, зачем, иначе сам от себя охуеешь, когда сборка начнёт вести себя неадекватно.