Dockerfile常用指令
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容器與容器雲》