Встречается на 60% собеседований по DevOps

Чем отличает COPY от ADD

Инструкции COPY и ADD в Dockerfile предназначены для копирования файлов и директорий с хост-машины в образ, но ADD обладает дополнительными возможностями: автоматическим извлечением локальных tar-архивов и поддержкой URL-источников. Основное правило: для простого копирования используйте COPY, а ADD — только когда нужны его расширенные функции.

Как это работает

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

  • COPY выполняет только копирование. Это предсказуемая и прозрачная операция: что указали, то и скопируется.
  • ADD дополнительно умеет:
    • распаковывать локальные архивы в форматах tar, tar.gz, tar.bz2, tar.xz (при этом распаковка происходит автоматически, без дополнительных команд);
    • загружать файлы по URL (например, ADD https://example.com/file.tar.gz /app/).

Пример

Типичный Dockerfile с использованием обеих инструкций:

dockerfile
FROM ubuntu:22.04

# Простое копирование локального файла
COPY app.py /app/app.py

# Копирование директории
COPY ./config /app/config

# ADD с распаковкой локального архива
ADD bundle.tar.gz /app/bundle

# ADD с загрузкой по URL (не рекомендуется для продакшена)
ADD https://example.com/data.tar.gz /tmp/data.tar.gz

В первом случае COPY копирует файл и директорию как есть. Во втором ADD автоматически извлекает содержимое bundle.tar.gz в /app/bundle. В третьем — скачивает архив по URL, но не распаковывает его (распаковка URL-архивов не выполняется).

Подводные камни

  • Кеширование слоёв: COPY лучше кешируется, так как Docker сравнивает содержимое копируемых файлов. Для ADD с URL кеш часто сбрасывается, потому что содержимое удалённого файла может измениться, и Docker не может проверить его без загрузки. Это замедляет сборку.
  • Неожиданная распаковка: ADD автоматически распаковывает локальные архивы. Если вы хотели просто скопировать архив, он будет извлечён, что может привести к неожиданной структуре каталогов.
  • Безопасность: загрузка файлов по URL внутри ADD выполняется на этапе сборки, что может быть небезопасно (атака на цепочку поставок, неконтролируемое содержимое). Лучше скачивать файлы отдельно и копировать через COPY.
  • Рекомендации Docker: официальная документация и линтеры (например, hadolint) настоятельно рекомендуют использовать COPY всегда, когда нет явной необходимости в распаковке архивов или загрузке по URL.

Когда использовать

  • Используйте COPY для всех обычных операций копирования файлов и директорий. Это делает Dockerfile более предсказуемым и ускоряет сборку за счёт кеширования.
  • Используйте ADD только в двух случаях:
    • нужно автоматически распаковать локальный tar-архив внутри образа;
    • требуется загрузить файл по URL непосредственно в образ (но лучше избегать этого из-за проблем с кешированием и безопасностью).

Коротко

  • COPY — простое копирование, ADD — копирование с дополнительными функциями (распаковка архивов, URL).
  • Для большинства задач выбирайте COPY: он предсказуем и лучше кешируется.
  • ADD используйте только для распаковки локальных архивов или загрузки по URL, осознавая риски.
  • Помните: ADD с URL не распаковывает архив, а только скачивает его.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы