COPY
和 ADD
都是 Dockerfile
中的指令禀晓,有著類似的作用矮嫉。它們?cè)试S我們將文件從特定位置復(fù)制到 Docker 鏡像中臊诊。
1坡慌、COPY指令
(1)COPY指令說(shuō)明
COPY
指令從 <src>
復(fù)制新的文件或目錄芽世,并將它們添加到 Docker 容器文件系統(tǒng)的 <dest>
的路徑下挚赊。
(2)COPY指令格式
COPY
有兩種格式:(和 RUN
指令一樣)
COPY [--chown=<user>:<group>] <src>... <dest>
-
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
(包含空格的路徑使用這種格式)
翻譯一下:
COPY [--chown=<user>:<group>] <源路徑>... <目標(biāo)路徑>
COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標(biāo)路徑>"]
(3)COPY指令使用
COPY
指令將從構(gòu)建上下文目錄中 <源路徑>
的文件或目錄,復(fù)制到新的一層的鏡像內(nèi)的 <目標(biāo)路徑>
位置济瓢。
比如:
COPY package.json /usr/src/app/
-
<源路徑>
:可以是多個(gè)荠割,甚至可以是通配符,其通配符規(guī)則要滿足 Go 的filepath.Match
規(guī)則旺矾,如下:
COPY hom* /mydir/ COPY hom?.txt /mydir/
-
<目標(biāo)路徑>
:可以是容器內(nèi)的絕對(duì)路徑蔑鹦,也可以是相對(duì)于工作目錄的相對(duì)路徑(工作目錄可以用WORKDIR
指令來(lái)指定)。目標(biāo)路徑不需要事先創(chuàng)建箕宙,如果目錄不存在嚎朽,會(huì)在復(fù)制文件前先行創(chuàng)建缺失目錄。
此外柬帕,還需要注意一點(diǎn)哟忍,使用 COPY
指令,源文件的各種元數(shù)據(jù)都會(huì)保留陷寝。比如讀锅很、寫(xiě)、執(zhí)行權(quán)限凤跑、文件變更時(shí)間等爆安。這個(gè)特性對(duì)于鏡像定制很有用,特別是構(gòu)建相關(guān)文件都在使用 Git 進(jìn)行管理的時(shí)候仔引。
(4)其他
在使用該指令的時(shí)候還可以加上 --chown=<user>:<group>
選項(xiàng)鹏控,來(lái)改變文件的所屬用戶及所屬組。
COPY --chown=55:mygroup files* /mydir/
COPY --chown=bin files* /mydir/
COPY --chown=1 files* /mydir/
COPY --chown=10:11 files* /mydir/
2肤寝、ADD指令
ADD
指令和 COPY
指令的格式和性質(zhì)基本一致当辐,但是在 COPY
基礎(chǔ)上增加了一些功能。
(1)ADD指令說(shuō)明
ADD
指令有一些額外的功能 :
-
ADD
指令可以讓你使用 URL 作為<src>
參數(shù)鲤看。當(dāng)遇到 URL 時(shí)候缘揪,可以通過(guò) URL 下載文件并且復(fù)制到<dest>
(容器中目標(biāo)路徑)。 -
ADD
的另一個(gè)特性是自動(dòng)解壓文件的能力。如果<src>
參數(shù)是一個(gè)可識(shí)別壓縮格式(tar, gzip, bzip2, …)的本地文件(注:無(wú)法實(shí)現(xiàn)同時(shí)下載并解壓)找筝,就會(huì)被解壓到指定容器文件系統(tǒng)的路徑<dest>
下蹈垢。
即:ADD
指令是將本地文件復(fù)制到容器中,也支持通過(guò) URL 進(jìn)行復(fù)制袖裕,但效率通常很低(不推薦使用)曹抬。
(2)ADD指令格式
ADD
有兩種格式:
ADD [--chown=<user>:<group>] <src>... <dest>
-
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
(包含空格的路徑使用這種格式)
(3)ADD指令使用
ADD
的最佳用途是將本地壓縮包文件自動(dòng)提取到鏡像中:
如下情況,自動(dòng)解壓縮的功能非常有用急鳄,比如官方鏡像 ubuntu
中:
FROM scratch
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
...
提示:但在某些情況下谤民,如果我們真的是希望復(fù)制個(gè)壓縮文件進(jìn)去,而不解壓縮疾宏,這時(shí)就不可以使用
ADD
命令了张足。
(4)不推薦使用ADD指令下載文件的原因
由于鏡像的體積很重要,所以強(qiáng)烈建議不要使用 ADD
從遠(yuǎn)程 URL 獲取文件坎藐,下載文件我們應(yīng)該使用 curl
或 wget
來(lái)代替为牍。
因?yàn)槿绻螺d的是個(gè)壓縮包,需要解壓縮岩馍,還需要額外的一層 RUN
指令進(jìn)行解壓縮碉咆。所以不如直接使用 RUN
指令,然后使用 wget
或者 curl
工具下載蛀恩,處理權(quán)限吟逝、解壓縮、然后清理無(wú)用文件更合理赦肋。
因此,這個(gè)功能其實(shí)并不實(shí)用励稳,而且不推薦使用佃乘。
示例:
我們應(yīng)該避免以下操作:(Dockerfile文件)
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things \ # 解壓
&& make -C /usr/src/things all \ # 編譯
&& rm -f /usr/src/things/big.tar.xz # 刪除
這個(gè)壓縮包解壓后,rm
命令處于獨(dú)立的鏡像層驹尼。
我們可以這樣做:
RUN mkdir -p /usr/src/things \
&& curl -SL http://example.com/big.tar.xz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things all
curl
會(huì)下載這個(gè)壓縮包并通過(guò)管道傳給 tar
命令進(jìn)行解壓趣避,這樣也就不會(huì)在文件系統(tǒng)中留下這個(gè)壓縮文件了。
對(duì)于不需要自動(dòng)解壓的文件或目錄新翎,應(yīng)該始終使用 COPY
程帕。
最后,認(rèn)準(zhǔn)一個(gè)原則:總是使用 COPY
(除非我們明確需要 ADD
)地啰。
(5)其他
在使用該指令的時(shí)候還可以加上 --chown=<user>:<group>
選項(xiàng)來(lái)改變文件的所屬用戶及所屬組愁拭。
ADD --chown=55:mygroup files* /mydir/
ADD --chown=bin files* /mydir/
ADD --chown=1 files* /mydir/
ADD --chown=10:11 files* /mydir/
3、總結(jié):
在 Docker 官方的 Dockerfile 最佳實(shí)踐文檔
中要求亏吝,盡可能的使用 COPY
岭埠,因?yàn)?COPY
的語(yǔ)義很明確,就是復(fù)制文件而已,而 ADD
則包含了更復(fù)雜的功能惜论,其行為也不一定很清晰许赃。最適合使用 ADD
的場(chǎng)合,就是所提及的需要自動(dòng)解壓縮的場(chǎng)景馆类。
另外需要注意的是混聊,ADD
指令會(huì)令鏡像構(gòu)建緩存失效,從而可能會(huì)令鏡像構(gòu)建變得比較緩慢乾巧。
因此在 COPY
和 ADD
指令中選擇的時(shí)候句喜,可以遵循這樣的原則,所有的文件復(fù)制均使用 COPY
指令卧抗,僅在需要自動(dòng)解壓縮的場(chǎng)景使用 ADD
指令藤滥。
參考: