概述看是相似的COPY 與 ADD 命令
Dockerfile 中提供了兩個非常相似的 COPY 和 ADD,本文嘗試解釋這兩個 的基本功能,以及其異同點,然後總結其各自適合的應用場景。 |
在使用 docker build 命令透過 Dockerfile 建立映象時,會產生一個 build 上下文(context)。所謂的 build 上下文就是 docker build 命令的 PATH 或 URL 指定的路徑中的檔案的集合。在映象 build 過程中可以引用上下文中的任何檔案,比如我們要介紹的 COPY 和 ADD 命令,就可以引用上下文中的檔案。
預設情況下 docker build -t testx . 命令中的 . 表示 build 上下文為當前目錄。當然我們可以指定一個目錄作為上下文,比如下面的命令:
$ docker build -t testx /home/nick/hc
我們指定 /home/nick/hc 目錄為 build 上下文,預設情況下 docker 會使用在上下文的根目錄下找到的 Dockerfile 檔案。
對於 COPY 和 ADD 命令來說,如果要把本地的檔案複製到映象中,那麼本地的檔案必須是在上下文目錄中的檔案。其實這一點很好解釋,因為在執行 build 命令時,docker 客戶端會把上下文中的所有檔案傳送給 docker daemon。考慮 docker 客戶端和 docker daemon 不在同一臺機器上的情況,build 命令只能從上下文中獲取檔案。如果我們在 Dockerfile 的 COPY 和 ADD 命令中引用了上下文中沒有的檔案,就會收到類似下面的錯誤:
WORKDIR 命令為後續的 RUN、CMD、COPY、ADD 等命令配置工作目錄。在設定了 WORKDIR 命令後,接下來的 COPY 和 ADD 命令中的相對路徑就是相對於 WORKDIR 指定的路徑。比如我們在 Dockerfile 中新增下面的命令:
WORKDIR /app COPY checkredis.py .
然後構建名稱為 testx 的容器映象,並執行一個容器檢視檔案路徑:
checkredis.py 檔案就是被複制到了 WORKDIR /app 目錄下。
如果僅僅是把本地的檔案複製到容器映象中,COPY 命令是最合適不過的。其命令的格式為:
COPY <src> <dest>
除了指定完整的檔名外,COPY 命令還支援 Go 風格的萬用字元,比如:
COPY check* /testdir/
# 複製所有 check 開頭的檔案
COPY check?.log /testdir/
# ? 是單個字元的佔位符,比如匹配檔案 check1.log
對於目錄而言,COPY 和 ADD 命令具有相同的特點:只複製目錄中的內容而不包含目錄自身。比如我們在 Dockerfile 中新增下面的命令:
WORKDIR /app COPY nickdir .
其中 nickdir 目錄的結構如下:
重新構建映象 testx,執行一個容器並檢視 /app 目錄下的內容:
這裡只有 file1 和 file2,少了一層目錄 nickdir。如果想讓 file1 和 file2 還儲存在 nickdir 目錄中,需要在目標路徑中指定這個目錄的名稱,比如:
WORKDIR /app COPY nickdir ./nickdir
ADD 命令的格式和 COPY 命令相同,也是:
ADD <src> <dest>
除了不能用在 multistage 的場景下,ADD 命令可以完成 COPY 命令的所有功能,並且還可以完成兩類超酷的功能:
解壓壓縮檔案並把它們新增到映象中
從 url 複製檔案到映象中
當然,這些功能也讓 ADD 命令用起來複雜一些,不如 COPY 命令那麼直觀。
如果我們有一個壓縮檔案包,並且需要把這個壓縮包中的檔案新增到映象中。需不需要先解開壓縮包然後執行 COPY 命令呢?當然不需要!我們可以透過 ADD 命令一次搞定:
WORKDIR /app ADD nickdir.tar.gz .
這應該是 ADD 命令的最佳使用場景了!
這是一個更加酷炫的用法!但是在 docker 官方文件的最佳實踐中卻強烈建議不要這麼用!!docker 官方建議我們當需要從遠端複製檔案時,最好使用 curl 或 wget 命令來代替 ADD 命令。原因是,當使用 ADD 命令時,會建立更多的映象層,當然映象的 size 也會更大(下面的兩段程式碼來自 docker 官方文件):
ADD RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things RUN make -C /usr/src/things all
如果使用下面的命令,不僅映象的層數減少,而且映象中也不包含 big.tar.xz 檔案:
RUN mkdir -p /usr/src/things \ && curl -SL \ | tar -xJC /usr/src/things \ && make -C /usr/src/things all
好吧,看起來只有在解壓壓縮檔案並把它們新增到映象中時才需要 ADD 命令!
在使用 COPY 和 ADD 命令時,我們可以透過一些技巧來加速映象的 build 過程。比如把那些最不容易發生變化的檔案的複製操作放在較低的映象層中,這樣在重新 build 映象時就會使用前面 build 產生的快取。比如筆者構建映象時需要用到下面幾個檔案:
其中 myhc.py 檔案不經常變化,而 checkmongo.py、checkmysql.py 和 checkredis.py 這三個檔案則經常變化,那麼我們可這樣來設計 Dockerfile 檔案:
WORKDIR /app COPY myhc.py . COPY check* ./
讓 COPY myhc.py . 單獨佔據一個映象層,當 build 過一次後,每次因 checkmongo.py、checkmysql.py 和 checkredis.py 這三個檔案變化而導致的重新 build 都不會重新 build COPY myhc.py . 映象層:
如上圖所示,第二步和第三步都沒有重新 build 映象層,而是使用了之前的快取,從第四步��開始重新 build 了映象層。當檔案 size 比較大且檔案的數量又比較多,尤其是需要執行安裝等操作時,這樣的設計對於 build 速度的提升還是很明顯的。所以我們應該儘量選擇能夠使用快取的 Dockerfile 寫法。
當第一次看到 COPY 和 ADD 命令時不免讓人感到疑惑。但分析之後大家會發現 COPY 命令是為最基本的用法設計的,概念清晰,操作簡單。而 ADD 命令基本上是 COPY 命令的超集(除了 multistage 場景),可以實現一些方便、酷炫的複製操作。ADD 命令在增加了功能的同時也增加了使用它的複雜度,比如從 url 複製壓縮檔案時弊大於利。希望本文能夠解去大家對 Dockerfile 中 COPY 和 ADD 命令的疑惑。
原文地址:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559985/viewspace-2674297/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Dockerfile:ADD VS COPYDocker
- Dockerfile ADD和COPY指令Docker
- Dockerfile小記之操作檔案的命令ADD©Docker
- PostgreSQL copy相關選項SQL
- windows copy命令詳解Windows
- SQL中copy命令使用SQL
- git add命令詳解Git
- SQLPLUS 的COPY命令SQL
- fuser 命令概述
- 『現學現忘』Docker基礎 — 38、COPY指令和ADD指令Docker
- 區分copy構造與copy賦值賦值
- Linux 命令(210)—— ssh-copy-id 命令Linux
- Linux命令ssh-copy-idLinux
- Copy of a Copy of a Copy
- iOS 理解copy與mutableCopyiOS
- 遊戲與電影:相似的外表,不同的靈魂遊戲
- GoldenGate的ADD SCHEMATRANDATA命令研究Go
- Copy與mutableCopy的個人理解
- Copy 與MutableCopy的區別
- rman_copy和基本命令記載
- 2.13.1 DBCA 命令語法概述
- SVN 命令列 遞迴add/del目錄下未add/del的檔案命令列遞迴
- 查詢相似的索引索引
- Oracle相關命令Oracle
- vagrant 相關命令
- Vim相關命令
- oem相關命令
- RMAN命令相關
- BGP相關命令
- 使用copy命令解決LONG型別的困擾型別
- [SQLSERVER] sqlserver T-SQL 執行detach/attach,copy 命令SQLServer
- Long型別的資料,利用COPY命令遷移型別
- 集合使用copy與mutableCopy的區別
- 深入剖析Redis系列(四) - Redis資料結構與全域性命令概述Redis資料結構
- 使用ADD_CUSTOM_COMMAND 新增自定義命令
- Spring(一):Spring概述及相關概念Spring
- ORACLE的Copy命令和create table,insert into的比較Oracle
- Oracle Stream概述與配置Oracle