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

«В чем разница между инструкциями COPY и ADD в Dockerfile?» — вопрос из категории DevOps, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Обе инструкции копируют файлы и директории из контекста сборки (хоста) в образ контейнера, но 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 часто безопаснее.