← Назад к вопросам

В чем разница между COPY и ADD в Docker?

1.3 Junior🔥 141 комментариев
#DevOps и инфраструктура

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# COPY vs ADD в Docker

Это часто задаваемый вопрос для Docker разработчиков. На первый взгляд кажется, что COPY и ADD одинаковые, но есть важные различия.

Быстрое сравнение

КомандаКопирует файлыРаспаковывает архивыБерёт из URLСложность
COPY✅ Да❌ Нет❌ НетПростая
ADD✅ Да✅ Да✅ ДаСложная

Правило: Используй COPY по умолчанию. ADD только если нужна специальная функциональность.

1. COPY — простое копирование

Основное назначение

СКОПИРОВАТЬ файлы и папки с хоста в контейнер.

FROM python:3.11

# Копируем requirements
COPY requirements.txt /app/

# Копируем исходный код
COPY src/ /app/src/

# Копируем конфиг
COPY config.yaml /app/config.yaml

WORKDIR /app
RUN pip install -r requirements.txt

Синтаксис

# Копировать файл
COPY source.txt /app/source.txt

# Копировать директорию
COPY ./src/ /app/src/

# Копировать несколько файлов
COPY file1.txt file2.txt file3.txt /app/

# Копировать с переименованием
COPY ./config.yaml /app/settings.yaml

# Wildcards
COPY *.txt /app/  # Копирует все .txt файлы
COPY ./src/**/*.py /app/src/  # Копирует рекурсивно

Внутри контейнера

FROM ubuntu:22.04

COPY myfile.txt /data/myfile.txt
COPY mydir/ /data/mydir/

# Результат в контейнере:
# /data/myfile.txt
# /data/mydir/file1.txt
# /data/mydir/file2.txt

2. ADD — копирование + особенности

Синтаксис идентичен COPY

FROM python:3.11

ADD requirements.txt /app/
ADD src/ /app/src/
ADD config.yaml /app/config.yaml

Но ADD имеет ДОПОЛНИТЕЛЬНЫЕ возможности:

Функция 1: Автоматическая распаковка архивов

FROM ubuntu:22.04

# Копируем tar.gz файл
ADD myapp.tar.gz /app/

# Результат:
# /app/  (распакован архив)
# /app/file1.txt
# /app/file2.txt
# /app/subdir/

# Поддерживаемые форматы:
# - .tar
# - .tar.gz
# - .tar.bz2
# - .tar.xz
# - .zip

Практический пример

# Загружаем архив с исходным кодом
ADD source-code-1.0.tar.gz /app/
WORKDIR /app
RUN ./build.sh

# Эквивалент с COPY требует дополнительных команд
COPY source-code-1.0.tar.gz /app/
WORKDIR /app
RUN tar -xzf source-code-1.0.tar.gz && rm source-code-1.0.tar.gz
RUN ./build.sh

Функция 2: Копирование из URL

FROM ubuntu:22.04

# ADD может скачать файл из интернета!
ADD https://example.com/data.tar.gz /app/data.tar.gz

# Если это архив - распакует автоматически
ADD https://example.com/code.tar.gz /app/code/
# Результат: /app/code/ (распакован)

COPY vs ADD: Подробное сравнение

Case 1: Простое копирование файлов

# ✅ COPY - правильный выбор
COPY requirements.txt /app/requirements.txt

# ⚠️ ADD - тоже работает, но неправильный выбор
ADD requirements.txt /app/requirements.txt

Оба работают одинаково. COPY предпочтительнее за прозрачность.

Case 2: Распаковка архива

# ❌ COPY не может распаковать
COPY myapp.tar.gz /app/
RUN cd /app && tar -xzf myapp.tar.gz && rm myapp.tar.gz

# ✅ ADD распакует автоматически
ADD myapp.tar.gz /app/
# Файлы уже распакованы в /app/

Но есть проблема:

# ADD распакует архив в целевую директорию
ADD app.tar.gz /app/
# Если архив содержит 'app/', результат:
# /app/app/files...
# Часто нужна дополнительная обработка

# Лучше быть явным
COPY app.tar.gz /tmp/
RUN cd /tmp && tar -xzf app.tar.gz && mv app/* /app/

Case 3: Скачивание из интернета

# ✅ ADD может скачать
ADD https://example.com/data.tar.gz /data/

# ❌ COPY не может
COPY https://example.com/data.tar.gz /data/  # ОШИБКА!

# Эквивалент с COPY + RUN
RUN curl -O https://example.com/data.tar.gz \
    && tar -xzf data.tar.gz -C /data \
    && rm data.tar.gz

Проблемы с ADD

1. Неожиданное поведение

ADD archive.tar.gz /app/

# Пользователь может ожидать:
# /app/archive.tar.gz (просто файл)

# На самом деле:
# /app/  (архив распакован!)
# /app/content/  (содержимое архива)

2. Layer caching

# COPY - кеш работает хорошо
COPY requirements.txt /app/requirements.txt
RUN pip install -r /app/requirements.txt

COPY src/ /app/src/  # Если requirements не изменился,
                     # слой переиспользуется

# ADD с URL - кеш может быть неправильным
ADD https://api.example.com/data.json /data.json
# Docker не знает, изменился ли файл на сервере
# Кеш может быть устаревшим

3. Безопасность

# Опасно - скачиваем файл из интернета без контроля
ADD https://example.com/unknown-file.tar.gz /app/

# Безопаснее - явно скачиваем и проверяем
RUN curl -O https://example.com/file.tar.gz \
    && echo 'abc123' | sha256sum -c - file.tar.gz \
    && tar -xzf file.tar.gz

Best Practices

✅ Используй COPY

FROM python:3.11-slim

# Копируем requirements
COPY requirements.txt /app/

# Копируем исходный код
COPY src/ /app/src/

# Копируем конфиги
COPY config/ /app/config/

WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python", "main.py"]

⚠️ Используй ADD только если нужна специальная функциональность

FROM ubuntu:22.04

# Нужна автоматическая распаковка архива
ADD app-v1.0.tar.gz /opt/

# Остальное - COPY
COPY startup.sh /opt/startup.sh
COPY config.yaml /opt/config.yaml

ENTRYPOINT ["/opt/startup.sh"]

✅ Лучше быть явным

# Вместо автоматической распаковки через ADD
ADD code.tar.gz /app/

# Лучше явно распаковать
COPY code.tar.gz /tmp/
RUN tar -xzf /tmp/code.tar.gz -C /app && rm /tmp/code.tar.gz

# Почему?
# 1. Понятнее что происходит
# 2. Контроль над результатом
# 3. Можно проверить контрольные суммы
# 4. Проще отладить

✅ Скачивание файлов

# ❌ Неправильно
ADD https://example.com/large-file.tar.gz /data/

# ✅ Правильно
RUN curl -fsSL https://example.com/large-file.tar.gz \
    -o /tmp/file.tar.gz && \
    tar -xzf /tmp/file.tar.gz -C /data && \
    rm /tmp/file.tar.gz

# ✅ Ещё лучше с проверкой контрольной суммы
RUN curl -fsSL https://example.com/large-file.tar.gz \
    -o /tmp/file.tar.gz && \
    echo "abc123def456..." | sha256sum -c - /tmp/file.tar.gz && \
    tar -xzf /tmp/file.tar.gz -C /data && \
    rm /tmp/file.tar.gz

Резюме для собеседования

Основное различие

COPY:

  • Копирует файлы и папки
  • Простая и понятная
  • Рекомендуется в 99% случаев
  • Хороший layer caching

ADD:

  • Копирует файлы и папки (как COPY)
    • Распаковывает архивы (tar, zip, etc)
    • Может скачивать из URL
  • Менее понятна, может дать неожиданный результат
  • Использовать только если нужна дополнительная функциональность

Лучшая практика

FROM python:3.11-slim

# Используй COPY для файлов
COPY requirements.txt /app/
COPY src/ /app/src/

# Используй RUN + curl для скачиваний
RUN curl -fsSL https://example.com/data.tar.gz | tar -xz -C /data

# Добавляй ADD только если архив уже в контексте build'а
ADD local-archive.tar.gz /app/  # Может быть оправдано

WORKDIR /app
RUN pip install -r requirements.txt

Это важное знание для оптимизации Docker образов и написания чистых Dockerfile'ов.