1、映象構建過程
包含Dockerfile目錄的所有內容稱為上下文,上下文通過docker build
命令傳入到Docker daemon後,便開始按照Dockerfile中的內容一層層構造映象。
為了提高映象構建的速度,Docker daemon會快取構建過程中的中間映象。當從一個已在快取中的基礎映象開始構建新映象時,會將Dockerfile中的下一條指令和基礎映象的所有子映象做比較,如果有一個子映象是由相同指令生成的,則命中快取,直接使用該映象(COPY/ADD指令還會比較檔案內容),一旦快取失效,則後續的指令都將生成新的映象,不在使用快取。
2、Dockerfile指令
ENV
為映象建立出來的容器宣告環境變數,還可以被dockerfile後面的指令使用。
ENV <key> <value>
ENV <key=value>
FROM
為後面的指令提供基礎映象,一個Dockerfile可以有多個FROM指令,這樣會構建多個映象。在每個映象構建完成後,Docker命令列介面會輸出該映象的ID。
FROM <image>:<tag>
COPY
複製檔案或目錄新增到新映象中。
COPY <src> <dest>
/
結尾),但必須是目標映象中的絕對路徑或者相對於WORKDIR的相對路徑。
ADD
和COPY一樣,但
還可以只想本地的壓縮歸檔檔案,該檔案複製到容器中時會被解壓提取
RUN
在前一條命令建立的映象基礎上建立一個容器,並在容器中執行命令,命令結束後commit
容器為新映象,該映象被Dockerfile中的下一條指令使用。
RUN <command> (shell格式)
RUN ["executable","param1","param2"] (exec格式,推薦)
shell格式,命令通過/bin/sh -c執行。
exec格式,命令直接執行,引數會被當成JSON陣列被Docker解析,所以必須使用雙引號,因為exec不會在shell中執行,所以環境變數的引數不會被替換。例如當執行 CMD ["echo","$HOME"]時候,$HOME不會做變數的替換,可以改寫為 CMD ["sh","-c","echo","$HOME"]。
CMD
提供容器執行時的預設值,預設值可以是一條指令,可以是一些引數。
CMD <command> (shell格式)
CMD ["executable","param1","param2"] (exec格式,推薦)
CMD ["param1","param2"] (為ENTRYPOINT指令提供引數)
一個Dockerfile中可以有多條CMD指令,但只有最後一條有效。
CMD vs RUN
RUN指令在構建映象時執行命令,並生成新的映象;CMD指令在構建映象時並不執行命令,而是在容器啟動時預設將CMD指令作為第一條執行的命令。
如果使用者在命令列介面執行docker run
命令時指定了命令引數,則會覆蓋CMD指令中的命令。
ENTRYPOINT
和CMD類似,讓容器在每次啟動時候執行相同的命令。
ENTRYPOINT <command> (shell格式)
ENTRYPOINT ["executable","param1","param2"] (exec格式,推薦)
一個Dockerfile中可以有多條ENTRYPOINT指令,但只有最後一條有效。
使用shell格式,ENTRYPOINT會忽略任何CMD指令和docker run命令引數,並且會執行在/bin/sh -c中,意味著該指令程式為/bin/sh -c的子程式,程式在容器中的PID不是1,且不能接受UNIX訊號。即當使用docker stop
exec格式,docker run傳入的引數會覆蓋CMD指令的內容,但不會覆蓋ENTRYPOINT
ONBUILD
新增一個將來執行的觸發器指令到映象中
3、實踐心得
-
使用標籤
docker build -t="image:v1"
-
謹慎選擇基礎映象
儘量選擇官方映象,linux映象大小關係:
busybox < debian < centos < ubuntu
構建映象只安裝使用必須的包。
FORM指令應該包含引數tag
-
充分利用快取
Docker daemon會順序執行Dockerfile中的指令,為了有效利用快取,
儘量將所有Dockerfile檔案中相同的部分都放到前面,不同的部分放到後面
。 -
正確使用ADD和COPY指令
首選COPY。
當在Dockerfile中的不同部分需要用到不同檔案時,不要一次性地將這些檔案都新增到映象中去,而是在需要時候逐個新增,這樣也有利於充分利用快取
。考慮映象大小問題,使用ADD獲取遠端URL壓縮包不是推薦做法,應該使用RUN wget或RUN curl代替。
-
RUN指令
為了Dockerfile易讀,使用比較長的RUN指令時可以使用
\
分隔多行。不要在一行中單獨使用RUN apt-get update。當軟體源更新後,會引起快取問題,導致RUN apt-get install失敗。應該改為:RUN apt-get updata && apt-get install。
提交映象是廉價的,不要害怕映象的層數過多,因此,不要將所有命令寫在一個RUN指令中。
-
不要在Dockerfile中做埠對映
使用EXPOSE指令會破壞Docker的可移植性
參考連結:
《Docker容器與容器雲》