這篇博文將幫助您理解兩個相似的Dockerfile指令(ADD和COPY)之間的區別,以及它們如何成爲如今的樣子,以及咱們對您應該使用哪條指令的建議。 (提示:不是ADD) 從Dockerfile構建Docker鏡像時,您能夠選擇兩個指令將目錄/文件添加到鏡像:ADD和COPY。兩條指令都遵循相同的基本形式,並完成了幾乎相同的事情:docker
ADD <src>... <dest>
COPY <src>... <dest>
複製代碼
在這兩種狀況下,都會複製目錄或文件()並將其添加到指定的路徑的容器的文件系統中。bash
所以,若是兩條指令都是相同的,爲何它們都存在,您應該使用哪一條?請仔細閱讀,找出答案。curl
若是您對ADD和COPY的細微差異不感興趣,只想回答「我應該使用哪個?」,您只須要知道:使用COPY。post
與COPY指令不一樣的是,ADD從一開始就是Docker的一部分,除了從構建上下文中複製文件以外,還支持一些其餘技巧。優化
ADD指令容許您使用URL做爲參數。提供URL時,將從URL下載文件並將其複製到。url
ADD http://foo.com/bar.go /tmp/main.go
複製代碼
上面的文件將從指定的URL下載並添加到容器的文件系統/tmp/main.go中。另外一種形式可讓你簡單地爲下載的文件指定目標目錄:spa
ADD http://foo.com/bar.go /tmp/
複製代碼
因爲參數以尾部"/"結尾,所以Docker會從URL中推斷出文件名並將其添加到指定的目錄中。在這種狀況下,一個名爲/tmp/bar.go的文件將被添加到容器的文件系統中。code
ADD的另外一個功能是可以自動解壓縮壓縮文件。若是參數是一個識別壓縮格式(tar,gzip,bzip2等)的本地文件,那麼它將被解壓到容器文件系統中的指定處。blog
ADD /foo.tar.gz /tmp/
複製代碼
上面的命令會致使foo.tar.gz歸檔文件的內容被解壓到容器的/ tmp目錄中。 有趣的是,URL下載和解壓功能不能一塊兒使用。任何經過URL複製的壓縮文件都不會自動解壓縮。ip
顯然,簡單的ADD指令後面有不少功能。雖然這使得ADD很是靈活,但並無使它具備特別的可預測性。如下是2013年12月針對ADD命令記錄的問題的一段引文:
在我看來,當前的ADD指令很是的神奇。它能夠添加本地和遠程文件。它有時會解壓一個文件,它有時不會解壓文件。若是某個文件是要複製的tar包,則意外解壓縮它。若是該文件是一個壓縮格式的tar包,須要解壓,則意外複製它。 - amluto
這個共識彷佛是ADD試圖作得太多並且讓用戶感到困惑。顯然,沒有人想要破壞與ADD現有用法的向後兼容性,因此決定添加一個更具可預測性的新指令。
當版本1.0的Docker發佈時,包含了新的COPY指令。與ADD不一樣的是,COPY直接將文件和文件夾從構建上下文複製到容器中。
COPY不支持URL做爲參數,所以它不能用於從遠程位置下載文件。任何想要複製到容器中的東西都必須存在於本地構建上下文中。
另外,COPY對壓縮文件沒有特別的處理。若是您複製歸檔文件,它將徹底按照出如今構建上下文中的方式落入容器中,而不會嘗試解壓縮它。
COPY實際上只是ADD的精簡版本,旨在知足大部分「複製文件到容器」的使用案例而沒有任何反作用。
若是如今還不明顯,Docker團隊的建議是在幾乎全部狀況下都使用COPY。
真的,使用ADD的惟一緣由是當你有一個壓縮文件,你必定想自動解壓到鏡像中。理想狀況下,ADD將被從新命名爲EXTRACT之類的內容,以真正將這一點引入Docker生態(一樣,出於向後兼容的緣由,這不太可能發生)。 好的,可是從遠程URL獲取軟件包的方法不是仍然有用嗎?技術上,是的,但在大多數狀況下,您可能會更好地運行curl或wget。考慮下面的例子:
ADD http://foo.com/package.tar.bz2 /tmp/
RUN tar -xjf /tmp/package.tar.bz2 \
&& make -C /tmp/package \
&& rm /tmp/package.tar.bz2
複製代碼
這裏咱們有一條ADD指令,它從一個URL中檢索一個包,而後是一條RUN指令,它將它解包,構建它,而後嘗試清理下載的存檔。
不幸的是,因爲軟件包檢索和rm命令在單獨的鏡像層中,咱們實際上並無在最終鏡像中節省任何空間(有關此現象的更詳細的解釋,請參閱個人優化docker鏡像文章)。
在這種狀況下,你最好像下面這樣作:
RUN curl http://foo.com/package.tar.bz2 \
| tar -xjC /tmp/package \
&& make -C /tmp/package
複製代碼
這裏咱們使用curl命令下載壓縮包,而後經過管道傳遞給tar命令解壓。這樣咱們就不會在咱們須要清理的文件系統上留下壓縮文件。
將遠程文件添加到鏡像中可能仍有正當理由,但這應該是明確的決定,而不是您的默認選擇。
最終,規則是這樣的:使用COPY(除非你肯定你須要ADD)。
原文地址:https://www.ctl.io/developers/blog/post/dockerfile-add-vs-copy/