Dockerfile'daki 'COPY' ve 'ADD' komutları arasındaki fark nedir?


2196

Dockerfile içindeki COPYve ADDkomutları arasındaki fark nedir ve ne zaman diğerinden daha fazla kullanırım?

COPY <src> <dest>

KOPYALAMA talimatı, yeni dosyaları kopyalar <src>ve yol üzerindeki kabın dosya sistemine ekler<dest>

ADD <src> <dest>

EKLE talimatı yeni dosyaları kopyalar <src>ve yol üzerindeki kabın dosya sistemine ekler <dest>.



9
Haziran 2018'de olduğu gibi, referans ADD'nin görüntüye (yani statik bir dosya) eklediğini, COPY ise kapsayıcıya eklediğini (yani görüntünün bir çalışma zamanı örneği) söylüyor. Şüphesiz bu, COPY'nin görüntünün Docker tarafından çalıştırıldığı her seferinde yürütüldüğünü veya belki de bu tutarsız bir terminolojinin bir örneğidir?
Chris Robinson

14
Sanırım bu tutarsız bir terminoloji
Daniel Stevens

6
@ChrisRobinson, COPYher çalıştırıldığında yürütülmesi imkansız olurdu , çünkü içeriği almak için orijinal içeriğe erişimi olması gerekmez.
Ken Williams

Yanıtlar:


2166

Davranışlarının daha ayrıntılı bir açıklaması için ADDve COPYbelgelerini kontrol etmelisiniz , ancak özetle, en büyük fark şunun ADDdaha fazlasını yapabilmesidir COPY:

  • ADD<src>URL olmasına izin verir
  • Aşağıdaki yorumlara atıfta bulunan ADD belgeler şunları belirtmektedir:

    Tanınmış bir sıkıştırma biçiminde (kimlik, gzip, bzip2 veya xz) yerel bir katran arşiviyse, dizin olarak açılır. Uzak URL'lerden gelen kaynaklar genişletilmez.

Dockerfiles yazmak için en iyi uygulamaların, sihrinin gerekli olmadığı COPYyerlerde kullanılmasını önerdiğini ADDunutmayın. Aksi takdirde, siz ( bu cevabı aramak zorunda olduğunuzdan beri ) bir gün kabınıza kopyalamak istediğinizde şaşıracaksınız keep_this_archive_intact.tar.gz, bunun yerine içeriği dosya sisteminize püskürtüyorsunuz.


65
Sadece bir şeyi açıklığa kavuşturmak istedim: ADD'yi bir .tar.gz URL'si ile kullanmak arşivi dosya sistemine SÖZLEMİYOR (Emin olmak için şu anda iki kez kontrol ettim ve onaylandı)
Cecile

42
Bu önemli bir bilgidir ve resmi Dockerfile referansının farkı bu şekilde netleştirmemesi suçtur.
Cheeso

1
Emin değilim, bu görüntüden görüntüye farklılık gösteriyorsa. Bir zip dosyası için meşgul kutusu resmi ve ADD kullandım. Sadece sıkıştırılmadan hedef dizinde göründü. Bence, çıkarma sadece tarball için olur, ama şimdi kontrol etmedim.
Santosh Kumar Arjunan

4
@SantoshKumarArjunan: Docker belgeleri, ADD ve otomatik katran çıkarma hakkında şunları If <src> is a local tar archive in a recognized compression format (identity, gzip, bzip2 or xz) then it is unpacked as a directory. Resources from remote URLs are not decompressed.
söylüyor

1
COPY, ADD için aynı desteği bulamadığım --from = <ad | dizin> 'e izin verir
Brandon

474

COPY dır-dir

'EKLE' ile aynı, ancak katran ve uzak URL işleme olmadan.

Doğrudan kaynak kodundan referans alın .


15
Bunu doğru mu görüyorum: varolmayan dizinleriADD de oluşturur . Bu nedenle, bu iş parçacığında bir şekilde cesaret kırılmasına rağmen, bir avantaj yazıyor COPYçünkü mkdirbazı
eli

3
COPY does that too @eli
bhordupur

Şimdiye kadarki en iyi açıklama. Neden kabul edilen cevap değil?
xdevx32

141

Bu noktada bazı resmi belgeler var: Dockerfiles Yazmak için En İyi Uygulamalar

Görüntü boyutu önemli olduğundan, ADDuzak URL'lerden paketleri almak için kullanılması kesinlikle önerilmez; curlveya wgetyerine kullanmalısınız . Bu şekilde, artık ihtiyaç duymadığınız dosyaları ayıklandıktan sonra silebilirsiniz ve görüntünüze başka bir katman eklemek zorunda kalmazsınız.

RUN mkdir -p /usr/src/things \
  && curl -SL http://example.com/big.tar.gz \
    | tar -xJC /usr/src/things \
  && make -C /usr/src/things all

ADD'S katran otomatik ayıklama özelliği gerektirmeyen diğer öğeler (dosyalar, dizinler) için her zaman kullanmalısınız COPY.



18
Docker tercih ettiğini söylüyor COPYçünkü daha şeffaf. Gönderen Docker Dosya İyi Uygulamalar : (2014/12/15) Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. That’s because it’s more transparent than ADD. COPY only supports the basic copying of local files into the container, while ADD has some features that are not immediately obvious.
schemar

115

Docker dokümanlarından:

EKLE veya KOPYALA

ADD ve COPY işlevsel olarak benzer olmakla birlikte, genel olarak konuşursak, COPY tercih edilir. Çünkü ADD'den daha şeffaf. COPY, yalnızca yerel dosyaların kapsayıcıya temel olarak kopyalanmasını destekler, ancak ADD'nin hemen belirgin olmayan bazı özellikleri (yalnızca yerel katran çıkarma ve uzak URL desteği gibi) vardır. Sonuç olarak, ADD için en iyi kullanım ADD rootfs.tar.xz / dosyasında olduğu gibi görüntüye yerel katran dosyası otomatik olarak çıkarılmasıdır.

Diğer: Dockerfiles yazmak için en iyi uygulamalar


46

Bir /usr/localgiriş kapsayıcısına xx.tar.gz eklemek istiyorsanız , sıkıştırılmış dosyayı açın ve sonra kullanılmayan sıkıştırılmış paketi kaldırın.

KOPYA için:

COPY resources/jdk-7u79-linux-x64.tar.gz /tmp/
RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local
RUN rm /tmp/jdk-7u79-linux-x64.tar.gz

Eklemek için:

ADD resources/jdk-7u79-linux-x64.tar.gz /usr/local/

ADD yalnızca yerel katran çıkarmayı destekler. Bunun yanı sıra, KOPYA üç katman kullanacaktır, ancak EKLE yalnızca bir katman kullanır.


3
Neden sadece iki kat değil? RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local && rm /tmp/jdk-7u79-linux-x64.tar.gz
Stephen C

25

COPY bir dosyayı / dizini ana makinenizden görüntünüze kopyalar.

ADD bir dosyayı / dizini ana makinenizden görüntünüze kopyalar, ancak uzak URL'leri alabilir, TAR dosyalarını ayıklayabilir vb.

COPYDosyaları ve / veya dizinleri derleme bağlamına kopyalamak için kullanın .

Kullan ADDvb, uzaktan kaynakları indirme TAR dosyaların ayıklanması için ..


5
benim gibi bir çaylak için mükemmel bir açıklama
uneq95

17

Docker belgelerinden: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy

"ADD ve COPY işlevsel olarak benzer olsa da, genel olarak konuşursak, COPY tercih edilir. Bunun nedeni ADD'den daha saydam olmasıdır. COPY yalnızca yerel dosyaların kapsayıcıya temel kopyalanmasını destekler, ADD'nin bazı özellikleri vardır (yalnızca yerel katran çıkarma ve sonuç olarak, ADD için en iyi kullanım ADD rootfs.tar.xz / dosyasında olduğu gibi görüntüye yerel katran dosyası otomatik olarak çıkarılmasıdır.

Bağlamınızdan farklı dosyalar kullanan birden fazla Dockerfile adımınız varsa, bunları bir kerede değil, tek tek kopyalayın. Bu, özel olarak gerekli dosyalar değişirse her adımın derleme önbelleğinin yalnızca geçersiz kılınmasını sağlar (adımı yeniden çalıştırılmaya zorlar).

Örneğin:

 COPY requirements.txt /tmp/
 RUN pip install --requirement /tmp/requirements.txt
 COPY . /tmp/

COPY'yi koymak yerine RUN adımı için daha az önbellek geçersizliğine neden olur. / tmp / yazmadan önce.

Görüntü boyutu önemli olduğundan, uzak URL'lerden paketleri almak için ADD'yi kullanmak kesinlikle önerilmez; bunun yerine curl veya wget kullanmalısınız. Bu şekilde, artık ihtiyaç duymadığınız dosyaları ayıklandıktan sonra silebilirsiniz ve görüntünüze başka bir katman eklemek zorunda kalmazsınız. Örneğin, aşağıdakileri yapmaktan kaçınmalısınız:

 ADD http://example.com/big.tar.xz /usr/src/things/
 RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
 RUN make -C /usr/src/things all

Bunun yerine, şöyle bir şey yapın:

 RUN mkdir -p /usr/src/things \
     && curl -SL htt,p://example.com/big.tar.xz \
     | tar -xJC /usr/src/things \
     && make -C /usr/src/things all

ADD'nin katran otomatik ayıklama özelliği gerektirmeyen diğer öğeler (dosyalar, dizinler) için her zaman COPY kullanmalısınız. "


7

Kaynak: https://nickjanetakis.com/blog/docker-tip-2-the-difference-between-copy-and-add-in-a-dockerile :

COPY ve ADD, benzer amaçlara hizmet eden Dockerfile talimatlarıdır. Dosyaları belirli bir konumdan Docker görüntüsüne kopyalamanızı sağlar.

COPY bir src ve hedef alır. Yalnızca ana makinenizden (Docker görüntüsünü oluşturan makine) Docker görüntüsünün kendisine yerel bir dosya veya dizinde kopyalamanızı sağlar.

ADD bunu da yapmanıza izin verir, ancak diğer 2 kaynağı da destekler. İlk olarak, yerel bir dosya / dizin yerine bir URL kullanabilirsiniz. İkinci olarak, bir tar dosyasını kaynaktan doğrudan hedefe çıkarabilirsiniz

ADD için geçerli bir kullanım örneği, yerel bir tar dosyasını Docker görüntünüzdeki belirli bir dizine ayıklamak istediğiniz zamandır.

Yerel dosyaları Docker görüntünüze kopyalıyorsanız, daha açık olduğu için her zaman COPY kullanın.


7

Bir Dockerfile oluştururken, dosyaları / dizinleri içine kopyalamak için kullanabileceğiniz iki komut vardır - ADDve COPY. İşlevlerinin kapsamı arasında küçük farklılıklar olsa da, aslında aynı görevi yerine getirirler.

Peki, neden iki komutumuz var ve birini veya diğerini ne zaman kullanacağımızı nasıl biliyoruz?

DOCKER ADDKOMUTANLIĞI

ADDKomutun daha eski olduğunu belirterek başlayalım COPY. Docker platformunun lansmanından bu yana, ADDtalimat komutlar listesinin bir parçası olmuştur.

Komut dosyaları / dizinleri belirtilen kapsayıcıdaki bir dosya sistemine kopyalar.

ADDKomutun temel sözdizimi :

ADD <src> … <dest>

Kopyalamak istediğiniz kaynağı ( <src>) ve ardından saklamak istediğiniz hedefi ( <dest>) içerir. Kaynak bir ADDdizinse içindeki her şeyi kopyalar (dosya sistemi meta verileri dahil).

Örneğin, dosya yerel olarak kullanılabiliyorsa ve dosyayı bir görüntünün dizinine eklemek istiyorsanız, şunu yazın:

ADD /source/file/path  /destination/path

ADDURL'den de dosya kopyalayabilir. Harici bir dosya indirebilir ve istenen hedefe kopyalayabilir. Örneğin:

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

Ek bir özellik, sıkıştırılmış dosyaları kopyalaması ve verilen hedefteki içeriği otomatik olarak çıkarmasıdır. Bu özellik yalnızca yerel olarak depolanan sıkıştırılmış dosyalar / dizinler için geçerlidir.

ADD source.file.tar.gz /temp

Sıkıştırılmış bir dosyayı / dizini bir URL'den indiremeyeceğinizi ve çıkaramayacağınızı unutmayın. Komut, yerel paketleri sisteme kopyalarken harici paketleri açmaz.

DOCKER COPYKOMUTANLIĞI

Bazı işlevsellik sorunları nedeniyle Docker, içeriği çoğaltmak için ek bir komut vermek zorunda kaldı COPY.

Yakından ilişkili ADDkomutunun aksine COPY, yalnızca bir atanmış işlevi vardır. Rolü, dosyaları / dizinleri belirli bir konumda varolan biçimlerinde çoğaltmaktır. Bu, sıkıştırılmış bir dosyanın çıkarılmasıyla ilgilenmediği, aksine olduğu gibi kopyaladığı anlamına gelir.

Talimat yalnızca yerel olarak saklanan dosyalar için kullanılabilir. Bu nedenle, harici dosyaları kapsayıcınıza kopyalamak için URL'lerle kullanamazsınız.

COPYTalimatı kullanmak için temel komut biçimini izleyin:

Kaynağı ve komutun içeriği aşağıdaki gibi ayıklamasını istediğiniz yeri yazın:

COPY <src> … <dest> 

Örneğin:

COPY /source/file/path  /destination/path 

Hangi komutu kullanmalı? (En İyi Uygulama)

Komutanın COPYgetirildiği koşullar düşünüldüğünde, tutmanın ADDbir zorunluluk meselesi olduğu açıktır . Docker, Dockerfiles yazmak için en iyi uygulamaları özetleyen resmi bir belge yayınladı.ADD .

Docker'ın resmi dokümantasyonu COPY, her zamankinden daha şeffaf olduğu için her zaman talimat olması gerektiğini not eder ADD.

Yerel derleme bağlamından bir kaba kopyalamanız gerekiyorsa, kullanmaya devam edin COPY.

Docker ekibi ayrıca ADDbir URL'den bir paket indirmek ve kopyalamak için kullanılmasını kesinlikle önermez . Bunun yerine, bir RUNkomut içinde wget veya curl kullanmak daha güvenli ve daha verimlidir . Bunu yaparak, ek bir görüntü katmanı oluşturmaktan kaçınır ve yerden tasarruf edersiniz.


4

Önemli Not

COPYDocker resmimde java paketini açmam gerekiyor . ADD kullanılarak oluşturulan docker görüntü boyutunu karşılaştırdığımda, COPY, tar -xzf * .tar.gz ve rm * .tar.gz kullanılarak oluşturulandan 180 MB daha büyüktü.

Bu, ADD'nin tar dosyasını kaldırmasına rağmen, hala bir yerde tutulduğu anlamına gelir. Ve bu görüntüyü büyütüyor !!


Bu Docker'ın en son sürümü için hala geçerli mi?
Navin

3

Docker 17.05 COPY, çok aşamalı yapılarda--from bayrakla birlikte kullanıldığından önceki yapı aşamalarındaki mevcut yapıları mevcut yapı aşamasına kopyalamak için .

dan dokümantasyon

İsteğe bağlı olarak COPY --from=<name|index>, kaynak konumunu kullanıcı tarafından gönderilen bir derleme bağlamı yerine kullanılacak bir önceki derleme aşamasına (FROM .. AS ile oluşturulmuş) ayarlamak için kullanılabilecek bir bayrağı kabul eder .


0
docker build -t {image name} -v {host directory}:{temp build directory} .

Bu, dosyaları görüntüye kopyalamanın başka bir yoludur. -V seçeneği geçici olarak derleme işlemi sırasında kullandığımız bir birimi oluşturur.

Bu, yalnızca derleme için bir ana bilgisayar dizini bağladığı için diğer birimlerden farklıdır. Dosyalar standart bir cp komutu kullanılarak kopyalanabilir.

Ayrıca, curl ve wget gibi, bir komut yığınında (tek bir kapta çalışır) çalıştırılabilir ve görüntü boyutunu çarpamaz. ADD ve COPY bağımsız bir kapsayıcıda çalıştırıldığından istiflenemez ve ek kapsayıcılarda yürütülen bu dosyalar üzerinde sonraki komutlar görüntü boyutunu çoğaltır:

Bu şekilde ayarlanan seçeneklerle:

-v /opt/mysql-staging:/tvol

Bir kapta aşağıdakiler yürütülür:

RUN cp -r /tvol/mysql-5.7.15-linux-glibc2.5-x86_64 /u1 && \
    mv /u1/mysql-5.7.15-linux-glibc2.5-x86_64 /u1/mysql && \

    mkdir /u1/mysql/mysql-files && \
    mkdir /u1/mysql/innodb && \
    mkdir /u1/mysql/innodb/libdata && \
    mkdir /u1/mysql/innodb/innologs && \
    mkdir /u1/mysql/tmp && \

    chmod 750 /u1/mysql/mysql-files && \
    chown -R mysql /u1/mysql && \
    chgrp -R mysql /u1/mysql

1
Bu seçeneği gördüğünüz docker sürümü nedir? Belgelenmemiş ve 1.12.1 istemcimde çalışmıyor.
BMitch

2
Aslında, bu özellik hala ana sürüme dahil edilmedi ve konu hakkında hala çok fazla tartışma var, bu yüzden uzun süre beklememeliyiz ... Daha fazla bilgi için hata raporuna bakın: github.com/ liman işçisi / liman işçisi / sayıları / 14080 .
jwatkins

1
Evet, böyle bir seçenek yok (en son sürüm 17.06'da kontrol edildi). Bu cevap yanıltıcı. unknown shorthand flag: 'v' in -v
Kirby

Gerçekten yanıltıcı yorum
Guido van Steen

Docker ciltlerinin cevabında burada yapacak bir şeyleri yoktu, lütfen doğrudan soruyu cevaplayın :), kolayca aşağı cevap.
Majid Ali Khan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.