В чем разница между инструкциями COPY и ADD в Dockerfile?

Ответ

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

COPY <src> <dest>

  • Назначение: Прямое и простое копирование локальных файлов/директорий.
  • Поведение: Копирует файлы «как есть». Это предпочтительный и более предсказуемый выбор в большинстве случаев.
# Копирование одного файла
COPY package.json /app/
# Копирование всей директории
COPY ./src /app/src

ADD <src> <dest>

  • Назначение: Копирование с дополнительными возможностями.
  • Поведение:
    1. Автоматическая распаковка локальных архивов (.tar, .tar.gz, .tar.bz2, .tar.xz, .gz) в месте назначения.
    2. Поддержка URL-адресов в качестве источника <src>. Файл скачивается из сети и копируется в образ.
# Распаковка локального архива в директорию /app
ADD application.tar.gz /app/
# Скачивание файла из сети
ADD https://example.com/file.txt /tmp/

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

  • Всегда используйте COPY, если вам не нужны специфические возможности ADD. Это делает Dockerfile более понятным и предсказуемым.
  • Избегайте ADD для загрузки удаленных файлов. Скачивание лучше выполнять явно с помощью RUN с curl или wget, так как это дает больше контроля (например, проверка контрольных сумм, обработка ошибок). Кэширование слоя с ADD из URL также работает иначе.
  • Распаковка архивов через ADD может быть неочевидной. Например, в архив могут входить скрытые файлы (вроде .git/), которые вы, возможно, не хотите копировать. Явная распаковка с помощью RUN tar -xzf часто безопаснее.

Ответ 18+ 🔞

Давай разберём эту историю с COPY и ADD, а то тут, бля, такой овердохуища тонкостей, что сам от себя охуеешь. Вроде оба копируют, а разница — как между «просто занести пиво» и «занести пиво с внезапным стриптизом». Не всегда же нужен стриптиз, правда?

COPY <src> <dest> — это наш работяга, прямолинейный чувак. Его задача проще некуда: взял файлы с хоста и положил в образ. Никаких фокусов, всё честно. Предсказуем, как восход солнца после хорошей пьянки. Его и надо юзать в 95% случаев.

# Кинул package.json куда надо — и всё
COPY package.json /app/
# Перекинул всю папку src — тоже без сюрпризов
COPY ./src /app/src

ADD <src> <dest> — это уже хитрая жопа с талантами. Он тоже копирует, но если видит архив (типа .tar.gz), то сам его, бля, распаковывает. Ещё он может файлы прямо из интернета скачать, если ему ссылку дать.

# Сам распакует архив в /app. Удобно? Бывает.
ADD application.tar.gz /app/
# Полезет в интернет и скачает файл. Вообще доверия ебать ноль к такому.
ADD https://example.com/file.txt /tmp/

Так когда что использовать?

  • Бери COPY всегда, если не уверен. Серьёзно, это как золотое правило. Хочешь предсказуемости — COPY. Волнение ебать не нужно, когда образ собираешь.
  • ADD для скачивания из сети — это пиздопроебибна идея. Лучше сделай RUN curl -o ... или RUN wget. Хотя бы контроль над процессом будет, а то ADD тебе скачает, а ты и не поймёшь, что там внутри, если ссылка кривая.
  • Распаковка архивов через ADD — тоже палка о двух концах. Он может тебе в образ незаметно натянуть какую-нибудь скрытую папку .git или ещё какую дичь из архива. Явно распаковать через RUN tar — надёжнее, хоть и дольше писать.

Короче, COPY — твой верный друг, а ADD — тот самый товарищ, с которым весело, но на которого лучше не полагаться в серьёзных делах.