Docker COPY: Dockerfile 最佳實踐
Docker有兩個類似的Dockerfile指令,COPY 和 ADD,它們都用於在映象中匯入檔案,本文將解釋為什麼最好使用COPY而不是ADD,除非您想要將本地tar包自動提取到映象中。
使用 COPY 指令的最佳實踐
此 Dockerfile 指令將一個或多個本地檔案或資料夾複製到目標的 docker 映象中去。
- COPY <source>… <destination>
- COPY ["<source>",… “<destination>”] (此格式對於包含空格的路徑是必需的)
舉個例子在 Dockerfile 中使用 COPY 指令
這就是如何在 Dockerfile 中使用 COPY 指令構建一個 Ruby應用程式簡單例子。
FROM ruby:2.5.1
WORKDIR /usr/src/app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
CMD ["./your-daemon-or-script.rb"]
它以 layers 為單位構建映象,從父映象 ruby:2.5.1 開始,使用 FROM 定義。
使用 WORKDIR 指令定義工作目錄,接下來可以使用 COPY 或者 ADD 指令。
在這種情況下,使用copy時,它將從本地源複製檔案。表示當前目錄中的檔案,到 WORKDIR 定義的位置。在上面的例子中,第二個COPY 指映象中工作目錄從當前目錄拷貝。
使用 COPY 建立映象 layers 的最佳實踐
Docker 建議使用 COPY 建立映象 layers,方法是在不同的 image layers 中保留不同的檔案上下文。這意味著重建映象是有效的。最不可能更改的檔案應該在較低的 layers 中,而最可能更改的檔案應該最後新增。
如果有多個dockerfile步驟使用來自不同檔案的上下文,請分別複製它們,而不是一次全部複製。這樣可以確保每個步驟的構建快取只有在特定需要的檔案發生更改時才失效。
–Best practices for writing Dockerfiles
這個原理在上面的dockerfile示例中得到了演示。通過複製 Gemfiles ,然後執行 Run bundle install,就可以使用安裝的ruby gems建立一個image layer,可以對其進行快取。最後兩個docker指令將應用程式的檔案複製到映象中,並使用 CMD 設定預設命令。
這意味著,如果更改應用程式的任何檔案,可以使用快取的父層和中間層重新生成Docker映象。這比從頭開始構建所有這些模型要高效得多。
為什麼你不應該使用 ADD 指令
ADD 指令的語法與 COPY 相似。除了將本地檔案和目錄複製到Docker映象中的目的地之外,它還具有一些附加功能。
- ADD <source>… <destination>
- ADD ["<source>",… “<destination>”] (此格式對於包含空格的路徑是必需的)
然而,Docker官方的Dockerfile最佳實踐指南指出,在大多數情況下,COPY 是優於 ADD 的首選指令。
儘管 ADD 和 COPY 在功能上相似,但一般來說,還是首選 COPY。這是因為它比 ADD 更透明。COPY 僅支援將本地檔案複製到容器中,而 ADD 具有一些不那麼明顯的功能(如本地tar提取和遠端url支援)。因此,ADD 的最佳用途是將本地tar檔案自動提取到映象中,如 ADD rootfs.tar.xz/
-— Best practices for writing Dockerfiles
ADD 的一個另一個附加特性是它可以從URL複製檔案,但Docker建議不要將其用於此目的。
從URL複製檔案的最佳實踐
如果 ADD 的源是一個url,它將下載檔案並將其複製到docker映象中的目的地。Docker認為,使用add從URL複製通常是不高效的,最好使用其他策略來包含所需的遠端檔案。
因為映象大小很重要,所以強烈建議不要使用 ADD 從遠端URL獲取包;您應該使用curl或wget。這樣,您就可以刪除提取後不再需要的檔案,而無需在映象中新增其他層。
-— Dockerfile Best Practices
例如,您應該避免執行以下操作:
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
相反,執行如下的操作:
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
你在何時應該使用 ADD 指令
如果 <source> 是一個可識別壓縮格式的本地tar檔案,那麼它會自動作為目錄解包到Docker映象中。例如:add rootfs.tar.xz/。這是在docker官方建議使用的ADD的場景。
對其他檔案或者目錄,不需要ADD的自動解壓能力的地方,你應該總是使用 COPY。