هنگام ایجاد یک Dockerfile، دو دستور ADD و COPY وجود دارد که شما می‌توانید از آن‌ها برای کپی کردن فایل‌ها یا دایرکتوری‌ها در آن استفاده کنید. اگرچه یکسری تفاوت‌های جزئی در محدوده عملکرد این دو دستور وجود دارد، اما اساس کارشان یکسان است.

اکنون این سؤال در ذهن ایجاد می‌شود که پس چرا ما دو دستور داریم و چگونه می‌توان فهمید چه زمانی از یکی یا دیگری استفاده نماییم؟

در این مقاله، هر دستور شرح داده شده و تفاوت آن دو تجزیه و تحلیل شده است. در انتها به شما، آموزش داده می‌شود که از هر دستور بهتر است در چه زمانی استفاده شود.

 

 

دستور ADD در Docker

در ابتدا باید اشاره کرد که دستور ADD قدیمی‌تر از دستور COPY است. بدین معنی که از زمان راه اندازی پلت فرم Docker، دستورالعمل ADD بخشی از لیست دستورات آن بوده است.

این دستور، فایل‌ها و دایرکتوری‌ها را در یک سیستم فایل از یک container مشخص کپی می‌کند.

ساختار اصلی دستور ADD به شرح زیر است:

ADD <src> … <dest>

این دستور شامل منبعی است که می‌خواهید کپی کنید (<src>) و سپس مقصدی که در آن می‌خواهید منبع را ذخیره کنید (<dest>). اگر منبع یک دایرکتوری است، ADD همه چیز داخل آن (از جمله metadata سیستم فایل) را کپی می‌کند.

به عنوان مثال، اگر فایل به صورت محلی در دسترس است و شما می‌خواهید آن را به دایرکتوری یک image اضافه کنید، عبارت زیر را تایپ نمایید:

ADD /source/file/path  /destination/path

دستور ADD می‌تواند فایل‌ها را از URL نیز کپی کند. این دستور می‌تواند یک فایل خارجی را بارگیری کرده و در مقصد مورد نظر کپی نماید. مثلا:

ADD http://source.file/url  /destination/path

 

این مطلب نیز ممکن است برای شما مفید باشد: نصب Docker در CentOS 8

 

یک ویژگی دیگر این است که این دستور فایل‌های فشرده را کپی کرده و به طور خودکار محتوا را در مقصد مورد نظر استخراج می‌نماید. این ویژگی تنها در مورد فایل‌ها یا دایرکتوری‌هایی اعمال می‌شود که بصورت محلی فشرده و ذخیره شده اند.
منبع و جایی که می‌خواهید محتوا را در آن استخراج کند، به صورت زیر وارد کنید:

ADD source.file.tar.gz /temp

به خاطر داشته باشید که نمی‌توانید یک فایل یا دایرکتوری فشرده شده را از آدرس اینترنتی بارگیری و استخراج نمایید. این دستور، بسته‌های خارجی را هنگام کپی کردن آن‌ها در سیستم فایل محلی باز نمی‌کند.

توجه: دستور ADD، یک منبع فشرده را تنها در صورتی استخراج می‌کند که در یک قالب فشرده سازی شناخته شده باشد که فقط بر اساس محتویات فایل (نه بر اساس نام فایل) است. فرمت‌های فشرده سازی شناخته شده شامل identity ،gzip ،bzip و xz است.

 

دستور Copy در Docker

به دلیل وجود برخی مشکلات عملکردی، Docker مجبور شد یک دستور اضافی (COPY) برای تکرار (کپی کردن) محتوا معرفی نماید.

بر خلاف دستور ADD، دستور COPY تنها یک تابع اختصاص داده شده دارد که فایل‌ها و دایرکتوری‌ها را در یک مکان مشخص در قالب موجود آن‌ها کپی کند. این بدان معناست که با استخراج یک فایل فشرده سروکار ندارد، بلکه آن را همانطور که هست کپی می‌کند.

این دستور را می‌توان تنها برای فایل‌های ذخیره شده بصورت محلی استفاده کرد. بنابراین، شما نمی‌توانید از آن برای کپی کردن فایل‌های خارجی (با URLها) در container خود استفاده کنید.

به منظور استفاده از دستور COPY، از فرمت زیر استفاده نمایید:

COPY <src> … <dest> 

مثلا:

COPY /source/file/path  /destination/path 

 

مقایسه دستور Copy و ADD در Docker

چرا در صورت وجود دستور مشابه، نیاز به افزودن یک فرمان جدید بود؟

این واقعیت که ADD دارای عملکردهای زیادی بود، در عمل مشکل ساز شد؛ زیرا بسیار غیرقابل پیش بینی رفتار می‌کرد. نتیجه چنین عملکرد غیرقابل اعتمادی اغلب به کپی کردن زمانی مشخص می‌شود که در زمان استخراج کپی می‌کنید و در زمان کپی کردن استخراج می‌نمایید.

Docker به دلیل کاربردهای فراوان موجود نتوانست کاملاً دستور را جایگزین کند. به منظور سازگاری با وضعیت قبل، امن‌ترین گزینه، اضافه کردن دستور COPY بود که یک فرمان با کاربرد کمتر و در عین حال قابل اطمینان‌تر است.

 

کدام دستور بهتر است استفاده شود

با توجه به دلایلی که دستور COPY معرفی شد، بدیهی است که وجود ADD یک امر ضروری بوده است. Docker یک سند رسمی منتشر کرده است که بهترین شیوه‌های نوشتن Dockerfiles را در آن نشان می‌دهد. در این سند، به صراحت در برابر استفاده از دستور ADD توصیه شده است.

در اسناد رسمی Docker ذکر شده است که COPY همیشه باید دستورالعمل اصلی باشد؛ زیرا شفاف‌تر از ADD است.

بنابراین، اگر می‌خواهید از محتویات محلی در یک container کپی کنید، به استفاده از COPY پایبند باشید.

 

این مطلب نیز ممکن است برای شما مفید باشد: بازنویسی کردن Entrypoint با استفاده از Docker Run

 

علاوه براین، تیم Docker به شدت از استفاده از ADD برای بارگیری و کپی کردن یک بسته از یک آدرس اینترنتی خودداری می‌کند. در عوض، استفاده از wget یا curl در دستور RUN ایمن‌تر و کارآمدتر است. با انجام این کار، از ایجاد یک لایه image اضافی اجتناب می‌کنید و در فضا صرفه جویی می‌نمایید.

فرض کنید می‌خواهید یک بسته فشرده را از یک URL بارگیری کرده، محتوا را استخراج و بسته فشرده را پاک نمایید.

به جای استفاده از ADD و اجرای دستور زیر:

ADD http://source.file/package.file.tar.gz /temp
RUN tar -xjf /temp/package.file.tar.gz \
  && make -C /tmp/package.file \
  && rm /tmp/ package.file.tar.gz

شما باید از دستور زیر استفاده کنید:

RUN curl http://source.file/package.file.tar.gz \
  | tar -xjC /tmp/ package.file.tar.gz \
  && make -C /tmp/ package.file.tar.gz

توجه: تنها زمانی که به استفاده از دستور ADD نیاز دارید، زمان استخراج فایل‌های tar محلی در image است.

 

 

 

منبع:

phoenixnap