什么是Dockerfile 文件
Dockerfile 文件
是用于構建 docker 鏡像的腳本文件,由一系列的指令
構成。- 通過
docker build
命令構建鏡像時,Dockerfile 文件中的指令會由上到下執行,每條 指令都將會構建出一個鏡像層,這就是鏡像的分層。- 因此,指令越多,層次就越多,構建的鏡像就越多,效率就會越低。
所以,在定義Dockerfile時,能在一個指令內完成的動作,就不要分為兩條。
文件名
通常情況下,該文件名為
Dockerfile
docker build 構建命令
【注意】 : 命令最后有個點
.
, 表示 在執行該命令的目錄下 尋找Dockerfile
文件。
這個點.
很關鍵。
$ docker build -t 鏡像名稱:tag .
指令
基本介紹
- 指令大小寫不敏感,但習慣上全用大寫;
- 指令后至少會攜帶一個參數;
#
號開頭的,表示這一行是注釋行。
FROM 指令
語法 :
FROM <image>[:tag]
例如 : FROM centos:7.9.2009
作用 :指定構建新鏡像所基于的基礎鏡像。
* 必須為 Dockerfile 文件的第一條。
* 若 鏡像的標簽 tag 不寫的話,默認就是 latest。
* 若 鏡像本地沒有的話,會先執行下載。
補充 : 一個scratch 鏡像。
* scratch 鏡像是一個空鏡像,是所有鏡像的 Base 鏡像。
* scratch 鏡像只能在Dockerfile 中被繼承,不能pull拉取,不能run,也沒有tag。
* scratch 是一個保留字,用戶不能作為自己的鏡像名稱使用。
* 使用 scratch 作為基礎鏡像意味著你從零開始構建你的鏡像,沒有預裝任何文件、庫或運行時環境。
* 這通常用于創建極其精簡的容器鏡像,尤其是對于靜態編譯的二進制文件來說非常有用。
MAINTAINER 指令
語法 :
MAINTAINER 作者名字 作者郵箱
例如 : MAINTAINER northcastle norcastle@123.com
作用 : 標注鏡像維護者的姓名和郵箱。
但是,官方現在已經不推薦使用此指令,而是用 【LABEL】 指令代替。
LABEL 指令
語法 :
LABEL key1=value1 key2=value2 ...
例如 : LABEL author=northcastle email=northcastle@123.com
作用 : 給鏡像添加元數據(metadata)。
特點 : 以鍵值對的方式定義,可以自定義任何的信息;信息會被包含在鏡像的json文件中。
查看 : 通過 docker inspect 命令查看鏡像元信息時可以查看到自定義的內容。
RUN 指令
語法1 :
RUN shell-command
例如 : RUN yum install -y vim
語法2 :
RUN ["executable", "param1", "param2", ...]
例如 : RUN [“yum”,“install”,“-y”,“vim”]
作用 : 在基于當前構建階段的鏡像上執行命令,并將執行的結果(包括文件系統的變化)保存為新的鏡像層。
補充 : 基于 centos 構建鏡像時,使用 yum 命令報錯的解決方案
在Dockerfile 中添加如下內容:RUN cd /etc/yum.repos.d/
RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
RUN yum makecache
RUN yum update -y但是,上述方案有一個缺點:鏡像層太大了,非常的臃腫。
WORKDIR 指令
語法 :
WORKDIR 工作路徑
例如 : WORKDIR /usr/local
作用 : 為容器內的文件系統設置一個基礎目錄,使得后續命令可以基于此目錄進行操作。
特點 :* 如果指定的目錄不存在,WORKDIR 會自動創建該目錄。* 這個目錄會被用作所有 RUN、CMD、ENTRYPOINT、COPY 和 ADD 指令的上下文路徑。* 可以寫多個 WORKDIR 指令。* 當寫多個時,第一個為絕對路徑,后續用相對路徑會基于第一個的絕對路徑。* docker run 的 -w 參數 可以覆蓋這個指令置頂的默認工作目錄。
ENV 指令
語法1 :
ENV key value
單個定義
語法2 :ENV key1=value1 key2=value2 ...
同時定義多個
作用:定義環境變量。1、在Dockerfile 中可以被后續的指令直接引用,減少重復代碼。2、運行容器時,可以通過 -e 參數動態的傳入環境變量的值,從而使配置更加靈活。例如:ENV wd=/usr/localWORKDIR $wdCMD ["sh","-c","echo $wd"]下面是運行容器時覆蓋的例子:
* 只有一個環境變量需要覆蓋時:
docker run --name xxx -e wd=xxx -it imageName:tag* 當有多個需要覆蓋時,就寫 多個 -e k1=v1 -e k2=v2
docker run --name xxx -e wd=xxx -e wd2=xxx -e wd3=xxx ... -it imageName:tag
注意 :
-e 參數,并不是所有情況下都能生效。
只有是與容器相關的才會生效,例如 CMD 指令是容器運行的程序入口,會生效。
但 WORKDIR 指令是在構建鏡像的時候用,這個對于容器來說就不會生效。
ARG 指令
語法 :
ARG 變量名[=默認值]
作用 : 定義在構建過程中使用的變量。
使用方式 :
* 如果有多個變量,則需要寫`多個ARG` 指令即可;
* 可以出現在FROM 指令之前,常用于指定 FROM 的基礎鏡像的版本;
* ARG 定義的變量只能在構建階段生效,容器運行后不可用。
* 構建時 使用 【--build-arg 變量名=值】 的方式 指定 變量的值,如果有多個變量,則重復寫多個即可。例如 Dockerfile 如下 :
FROM centos:centos7.9.2009
ARG wd=/usr # 定義變量
WORKDIR $wd
CMD ["/bin/bash"]構建命令 :
docker build -t mycentos:1.0 --build-arg wd=/usr/local .
此命令即將 變量 wd 的值覆蓋成 [/usr/local]
ADD 指令
語法1 :
ADD src dest
語法2 :ADD ["src","dest"]
作用: 將 構建上下文中的 文件/目錄(src) 復制到 容器中指定的路徑中 (dest)。注意:
* src 可以是URL,會自動下載該路徑的資源并添加到鏡像中;
* src 可以是壓縮文件,復制到容器中后會自動解壓;
* src 可以是目錄,但不建議是目錄,因為會把該目錄下所有的內容全都復制到鏡像中;
* dest 是一個絕對路徑,最后要添加上斜杠[/],表示 一個目錄;
* dest 如果沒有[/] 則表示將原文件 復制到容器中并重命名為 dest 的名稱。例如 :
ADD hello.java /usr/local/javafile/
將 Dockerfile 文件所在目錄下的 hello.java 文件 復制到 鏡像的 /usr/local/javafile/ 目錄下。
特別注意:
【構建上下文限制】:* 當您構建一個 Docker 鏡像時,您通過 docker build 命令指定一個構建上下文(通常是包含 Dockerfile 的目錄)。* Docker 客戶端會將這個上下文發送給 Docker 守護進程,這意味著 ADD 和 COPY 指令只能訪問該上下文內的文件。* 因此,雖然 <src> 可以采用相對路徑形式來指向上下文內的文件或目錄,但它不能直接引用上下文之外的絕對路徑。【相對路徑 vs 絕對路徑】:
* 在 Dockerfile 中,ADD 指令的 <src> 參數通常使用相對于構建上下文的路徑。
* 如果您嘗試提供一個位于構建上下文外部的絕對路徑,比如 /home/user/file.txt,Docker 將無法找到該文件,并導致構建失敗。
COPY 指令
語法1 :
COPY src dest
語法2 :COPY ["src","dest"]
作用 :從主機的文件系統中復制文件或目錄到 Docker 鏡像中的指定位置。注意 :
* 不支持自動解壓縮 tar 文件;
* 不支持從 URL 下載文件;
* 行為單一,推薦使用。例如 :
COPY . /usr/loca/hostfile/
將 構建上下文 目錄中的所有文件 全都復制到 /usr/local/hostfile/ 目錄中去COPY f1 f2 f3 /usr/local/files/
COPY ["f1","f2","f3","/usr/local/files/"]
支持寫多個文件,中間用空格隔開。COPY *.txt /usr/local/allfiles/
支持通配符 *
EXPOSE 指令
語法1 :
EXPOSE port1 port2 ...
默認以 TCP 協議的方式 聲明端口號 (可以寫多個)
語法2 :EXPOSE port/protocol ...
以 指定protocol協議的方式 聲明端口號 (可以寫多個)
作用 : 聲明容器運行時監聽的網絡端口。
注意 :
* 它并不直接將端口暴露給主機,而是作為一種文檔化手段,告知使用者該容器希望在運行時開放哪些端口。
* 真正的端口映射 需要在 docker run 時 通過 -p 參數指定
* 例如 : docker run --name t1 -p 8081:8080 -d tomcat:8.5.49
* 將主機端口 8081 與 容器端口 8080 進行映射,這樣訪問主機的 8081 端口即可訪問到容器的 8080端口。
CMD 指令(*)
作用:
【提供默認的容器啟動命令】:當用戶沒有通過 docker run 命令指定任何命令時,將使用 CMD 提供的默認命令來啟動容器。
【為 ENTRYPOINT 提供默認參數】:如果 Dockerfile 中同時定義了 ENTRYPOINT 和 CMD,那么 CMD 的值會被作為參數傳遞給 ENTRYPOINT。這種組合非常強大,因為它允許你創建一個具有固定入口點(如腳本或應用)的基礎鏡像,并且允許最終用戶覆蓋默認參數而不必重新定義整個命令。
語法1 :
CMD command param1 param2...
例如 :CMD cal -y 2005
command
是 shell 命令, 會在 /bin/sh -c 中運行命令,這意味著它會在一個 shell 環境中執行。
會被 docker run 后面的 命令覆蓋,但不支持拼接 ducker run 后面的參數。
語法2 :
CMD ["executable","param1","param2" ...]
例如:CMD [“cal”,“-y”,“2005”]
executable
是可執行文件的路徑,后面的是參數;
會被 docker run 后面的 命令覆蓋,但不支持拼接 ducker run 后面的參數。
語法3 :
CMD ["param1","param2",...]
例如:
ENTRYPOINT [“echo”]
CMD [“hello”,“world”]
給ENTRYPOINT
指令中聲明的 可執行腳本 提供默認參數,
會被 docker run 命令后面的 參數完全覆蓋,不支持拼接參數。
ENTRYPOINT 指令(*)
作用:配置容器啟動時要運行的命令。
* 并且這個命令不容易被覆蓋,除非顯式地使用 --entrypoint 標志。
與 CMD 指令結合使用時,ENTRYPOINT 可以提供固定的入口點,而 CMD 則可以用來指定默認參數,這些參數可以在運行容器時被用戶提供的參數覆蓋。
語法1 :
ENTRYPOINT command param1 param2...
例如 :ENTRYPOINT cal -y 2005
command
是 shell 命令, 會在 /bin/sh -c 中運行命令,這意味著它會在一個 shell 環境中執行。
會被 docker run 后面的 命令覆蓋,但不支持拼接 ducker run 后面的參數。
語法2 :
ENTRYPOINT ["executable","param1","param2" ...]
例如:ENTRYPOINT [“cal”,“-y”,“2005”]
executable
是可執行文件的路徑,后面的是參數;
支持 docker run 后面的參數 與 executable 命令進行拼接。
【組合
CMD
指令一起使用 】:
例如:
ENTRYPOINT [“echo”]
CMD [“hello”,“world”]
給ENTRYPOINT
指令中聲明的 可執行腳本 提供默認參數,
會被 docker run 命令后面的 參數完全覆蓋,不支持拼接參數。
CMD & ENTRYPOINT 的小結
ONBUILD 指令
語法 :
ONBUILD [INSTRUCTION]
[INSTRUCTION]
:可以是任何有效的 Dockerfile 指令,如RUN, COPY, ADD, ENV,
等等。
但 ONBUILD 不支持FROM, MAINTAINER, ONBUILD
這幾個指令作為其參數。
例如 : ONBUILD RUN yum installl -y vim
作用 :
* 在當前鏡像被用作其他鏡像的基礎鏡像時,觸發特定的操作。
* 當一個鏡像(我們稱它為父鏡像)包含 ONBUILD 指令,并且另一個 Dockerfile 使用這個父鏡像作為基礎鏡像(通過 FROM 指令),那么在執行 FROM 指令后,立即觸發并執行該父鏡像中定義的所有 ONBUILD 后面的指令。
VOLUME 指令
語法1 :
VOLUME container_path
語法2 :VOLUME ["container_path1","container_path2"...]
作用 : 在容器內定義多個持久化的掛載點,用于數據的持久化。但是,這種方式并不能指定宿主機上對應的持久化目錄。查看 : 通過 [docker inspect 容器ID] 命令,可以查看容器的詳細信息,其中,有一個 Mounts 數組,可以查看到對應的持久化數據卷的詳細信息。
補充 :
更推薦使用docker run --name c1 -v host_path:container_path image:tag
中的-v
參數的方式進行數據卷的掛載。
這種方式更直觀。
build cache
概述
Docker Daemon
通過Dockerfile
構建鏡像時,當發現即將新構建出的鏡像層與本地已經存在的某個鏡像層重復時,默認會復用已經存在的鏡像層。這種機制稱為docker build cache 機制
。- 此機制不僅加快了鏡像的構建過程,同時也大量節省了Docker宿主機的空間。
docker build cache
并不是占用內存的 cache,而是一種對磁盤中相應鏡像層的檢索復用機制。所以無論是關閉Docker引擎,還是重啟Docker宿主機,只要該鏡像層存在就會復用。
失效的情況
1、Dockerfile 本身發生了變化 : 從發生變化指令開始,后面的所有指令層全部失效。(因為后面的是基于前面的層)
2、Dockerfile 文件內容未變,但是 ADD/COPY 指令所添加/復制的源文件發生了變化,則后續的全部失效。(即文件系統變了)
3、RUN 指令的外部依賴發生改變。(也是相當于文件系統變了)
4、明確指定不使用 build cache [--no-cache 參數]構建命令 :docker build --no-cache -t xxx:tag清理cache : docker system prune