Обидві інструкції додають файли в образ, але ADD робить більше, і саме це робить його менш передбачуваним.
COPY - просто копіює файли й каталоги з контексту збирання (або з іншої стадії --from=):
COPY composer.json composer.lock ./
COPY --chown=www-data:www-data . /var/www/html
ADD уміє ще й:
- завантажувати файли за URL:
ADD https://example.com/app.tar.gz /tmp/; - автоматично розпаковувати локальні архіви (
.tar,.tar.gz,.tar.xz) у каталог призначення; - клонувати Git-репозиторії:
ADD https://github.com/org/repo.git#v1.2 /src.
Чому за замовчуванням - COPY:
- передбачуваність:
COPY archive.tar.gz /app/копіює архів як файл.ADDз тим самим рядком розпакує його - поведінка залежить від типу файлу; - кеш: для URL Docker мусить завантажити файл, щоб перевірити, чи він змінився;
- безпека: завантаження з інтернету без перевірки вмісту - ризик ланцюжка постачання.
Коли ADD доречний:
- розпакувати локальний архів одним кроком (наприклад, бінарник з архіву поруч із Dockerfile);
- завантажити файл із перевіркою контрольної суми - сучасний
ADDпідтримує--checksum=sha256:..., тож вміст гарантовано той, що очікувався; - Git-репозиторій як джерело без окремого
git cloneв образі.
Корисні параметри обох інструкцій:
--chown=user:group- власник файлів одразу при копіюванні. ОкремийRUN chown -RпісляCOPYстворює ще один шар з копією всіх файлів - образ подвоюється в розмірі;--chmod=755- права доступу;--link- копіювання незалежним шаром, який не інвалідується при зміні попередніх шарів (корисно для фінальних стадій).
Що потрапляє в контекст визначає .dockerignore - без нього COPY . . скопіює .git, node_modules, .env і локальні логи.
Правило Docker Best Practices: COPY для локальних файлів; ADD - лише коли потрібні його додаткові можливості, і то свідомо.