一、概述
Dockerfile 是一個用來構(gòu)建鏡像的文本文件,文本內(nèi)容包含了一條條構(gòu)建鏡像所需的指令和說明。
官方文檔:
https://docs.docker.com/engine/reference/builder/
Dockerfile 示例:
https://github.com/dockerfile/
二、Dockerfile 結(jié)構(gòu)
Dockerfile 結(jié)構(gòu)主要分為四部分:
基礎(chǔ)鏡像信息
維護者信息
鏡像操作指令
容器啟動時執(zhí)行指令 (CMD/ENTRYPOINT)
【溫馨提示】Dockerfile 每行支持一條指令,每條指令可攜帶多個參數(shù)(支持&&),支持使用以“#“號開頭的注釋(jason 文件不支持#注釋),但是也非必須滿足上面的四點。
三、常用 Dockerfile 操作指令
ARG—— 定義創(chuàng)建鏡像過程中使用的變量 ,唯一一個可以在 FROM 之前定義 。
FROM——基于某個鏡像, FROM前面只能有一個或多個ARG指令 。
MAINTAINER(已棄用) —— 鏡像維護者姓名或郵箱地址 。
VOLUME —— 指定容器掛載點到宿主機自動生成的目錄或其他容器
RUN——執(zhí)行鏡像里的命令,跟在 liunx 執(zhí)行命令一樣,只需要在前面加上 RUN 關(guān)鍵詞就行。
COPY——復(fù)制本地(宿主機)上的文件到鏡像。
ADD——復(fù)制并解壓(宿主機)上的壓縮文件到鏡像。
ENV——設(shè)置環(huán)境變量。
WORKDIR —— 為 RUN、CMD、ENTRYPOINT、COPY 和 ADD 設(shè)置工作目錄,就是切換目錄 。
USER —— 為 RUN、CMD、和 ENTRYPOINT 執(zhí)行命令指定運行用戶。
EXPOSE —— 聲明容器的服務(wù)端口(僅僅是聲明) 。
CMD—— 容器啟動后執(zhí)行的命令 ,多個 CMD 只會執(zhí)行最后一個,跟 ENTRYPOINT 的區(qū)別是,CMD 可以作為 ENTRYPOINT 的參數(shù),且會被 yaml 文件里的 command 覆蓋。
ENTRYPOINT—— 容器啟動后執(zhí)行的命令 ,多個只會執(zhí)行最后一個。
HEALTHCHECH —— 健康檢查 。
ONBUILD——它后面跟的是其它指令,比如 RUN, COPY 等,而這些指令,在當前鏡像構(gòu)建時并不會被執(zhí)行。只有當以當前鏡像為基礎(chǔ)鏡像,去構(gòu)建下一級鏡像的時候才會被執(zhí)行。
LABEL——LABEL 指令用來給鏡像添加一些元數(shù)據(jù)(metadata),以鍵值對的形式 ,替換 MAINTAINER。
1)鏡像構(gòu)建(docker build)
dockerbuild-ttext:v1.--no-cache #要在構(gòu)建后將映像標記到多個存儲庫中,請在運行命令-t時添加多個參數(shù) dockerbuild-tshykes/myapp:1.0.2-tshykes/myapp:latest. ###參數(shù)解釋 #-t:指定鏡像名稱 # . :當前目錄Dockerfile #-f:指定Dockerfile路徑 #--no-cache:不緩存
2)運行容器測試(docker run)
#非交互式運行 dockerruncentos:7.4.1708/bin/echo"Helloworld" ###交互式執(zhí)行 #-t:在新容器內(nèi)指定一個偽終端或終端。 #-i:允許你對容器內(nèi)的標準輸入(STDIN)進行交互。 #會登錄到docker環(huán)境中,交互式 dockerrun-itcentos:7.4.1708/bin/bash #-d:后臺執(zhí)行,加了-d 參數(shù)默認不會進入容器 dockerrun-itdcentos:7.4.1708/bin/bash ###進入容器 #在使用-d 參數(shù)時,容器啟動后會進入后臺。此時想要進入容器,可以通過以下指令進入: #docker exec -it :推薦大家使用 docker exec -it 命令,因為此命令會退出容器終端,但不會導(dǎo)致容器的停止。 #docker attach:容器退出,會導(dǎo)致容器的停止。 dockerexec-itb2c0235dc53/bin/bash dockerattachb2c0235dc53
3)ARG
構(gòu)建參數(shù),與 ENV 作用一致。不過作用域不一樣。ARG 設(shè)置的環(huán)境變量僅對 Dockerfile 內(nèi)有效,也就是說只有 docker build 的過程中有效,構(gòu)建好的鏡像內(nèi)不存在此環(huán)境變量。唯一一個可以在 FROM 之前定義 。構(gòu)建命令 docker build 中可以用 --build-arg <參數(shù)名>=<值> 來覆蓋。
語法格式:
ARG<參數(shù)名>[=<默認值>]
示例:
#在FROM之前定義ARG,只在FROM中生效 ARGVERSION=laster FROMcentos:${VERSION} #在FROM之后使用,得重新定義,不需要賦值 ARGVERSION RUNecho$VERSION>/tmp/image_version
4)FROM
定制的鏡像都是基于 FROM 的鏡像 ,【必選項】
語法格式:
FROM[--platform=] [AS ] FROM[--platform= ] [: ][AS ] FROM[--platform= ] [@ ][AS ]
如果引用多平臺圖像,可選--platform標志可用于指定圖像的平臺。FROM例如,linux/amd64、 linux/arm64或windows/amd64。默認情況下,使用構(gòu)建請求的目標平臺。全局構(gòu)建參數(shù)可用于此標志的值,例如允許您將階段強制為原生構(gòu)建平臺 ( --platform=$BUILDPLATFORM),并使用它交叉編譯到階段內(nèi)的目標平臺。
示例:
ARGVERSION=latest FROMbusybox:$VERSION #FROM--platform="linux/amd64"busybox:$VERSION ARGVERSION RUNecho$VERSION>image_version
5)MAINTAINER(已棄用)
鏡像維護者信息
語法格式:
MAINTAINER
示例:
LABELorg.opencontainers.image.authors="SvenDowideit@home.org.au"
6)VOLUME
定義匿名數(shù)據(jù)卷。在啟動容器時忘記掛載數(shù)據(jù)卷,會自動掛載到匿名卷。
作用:
避免重要的數(shù)據(jù),因容器重啟而丟失,這是非常致命的。
避免容器不斷變大。
在啟動容器 docker run 的時候,我們可以通過 -v 參數(shù)修改掛載點。
語法格式:
#后面路徑是容器內(nèi)的路徑,對應(yīng)宿主機的目錄是隨機的 VOLUME["<路徑1>","<路徑2>"...] VOLUME<路徑>
示例:
FROMubuntu RUNmkdir/myvol RUNecho"helloworld">/myvol/greeting VOLUME/myvol
7)RUN
用于執(zhí)行后面跟著的命令行命令。
語法格式:
RUN (shell形式,命令在 shell 中運行,默認/bin/sh -c在 Linux 或cmd /S /CWindows 上)
RUN ["executable", "param1", "param2"](執(zhí)行形式)
示例:
#以下三種寫法等價 RUN/bin/bash-c'source$HOME/.bashrc; echo$HOME' RUN/bin/bash-c'source$HOME/.bashrc;echo$HOME' RUN["/bin/bash","-c","source$HOME/.bashrc;echo$HOME"]
8)COPY
拷貝(宿主機)文件或目錄到容器中,跟 ADD 類似,但不具備自動下載或解壓的功能 。所有新文件和目錄都使用 0 的 UID 和 GID 創(chuàng)建,除非可選--chown標志指定給定的用戶名、組名或 UID/GID 組合以請求復(fù)制內(nèi)容的特定所有權(quán)。
語法格式:
COPY[--chown=: ] ... COPY[--chown= : ][" ",..." "]
示例:
#添加所有以“hom”開頭的文件: COPYhom*/mydir/ # ?替換為任何單個字符,例如“home.txt”。 COPYhom?.txt/mydir/ #使用相對路徑,并將“test.txt”添加到/relativeDir/: COPYtest.txtrelativeDir/ #使用絕對路徑,并將“test.txt”添加到/absoluteDir/ COPYtest.txt/absoluteDir/ #修改文件權(quán)限 COPY--chown=55:mygroupfiles*/somedir/ COPY--chown=binfiles*/somedir/ COPY--chown=1files*/somedir/ COPY--chown=10:11files*/somedir/
9)ADD
拷貝文件或目錄到容器中,如果是 URL 或壓縮包便會自動下載或自動解壓 。
ADD 指令和 COPY 的使用格類似(同樣需求下,官方推薦使用 COPY)。功能也類似,不同之處如下:
ADD 的優(yōu)點:在執(zhí)行 <源文件> 為 tar 壓縮文件的話,壓縮格式為 gzip, bzip2 以及 xz 的情況下,會自動復(fù)制并解壓到 <目標路徑>。
ADD 的缺點:在不解壓的前提下,無法復(fù)制 tar 壓縮文件。會令鏡像構(gòu)建緩存失效,從而可能會令鏡像構(gòu)建變得比較緩慢。具體是否使用,可以根據(jù)是否需要自動解壓來決定。
語法格式:
ADD[--chown=: ] ... ADD[--chown= : ][" ",..." "]
示例:
#通配符 ADDhom*/mydir/ #相對路徑,拷貝到WORKDIR目錄下relativeDir/ ADDtest.txtrelativeDir/ #絕對路徑 ADDtest.txt/absoluteDir/ #更改權(quán)限 ADD--chown=55:mygroupfiles*/somedir/ ADD--chown=binfiles*/somedir/ ADD--chown=1files*/somedir/ ADD--chown=10:11files*/somedir/
ADD 和 COPY 的區(qū)別和使用場景:
ADD 支持添加遠程 url 和自動提取壓縮格式的文件,COPY 只允許從本機中復(fù)制文件
COPY 支持從其他構(gòu)建階段中復(fù)制源文件(--from)
根據(jù)官方 Dockerfile 最佳實踐,除非真的需要從遠程 url 添加文件或自動提取壓縮文件才用 ADD,其他情況一律使用 COPY
10)ENV
設(shè)置環(huán)境變量,定義了環(huán)境變量,那么在后續(xù)的指令中,就可以使用這個環(huán)境變量。
語法格式:
ENV= = ... #省略"="此語法不允許在單個ENV指令中設(shè)置多個環(huán)境變量,并且可能會造成混淆。 ENV
示例:
ENVJAVA_HOME=/usr/local/jdk ENVMY_NAME="JohnDoe"MY_DOG=RexTheDog MY_CAT=fluffy #此語法不允許在單個ENV指令中設(shè)置多個環(huán)境變量,并且可能會造成混淆。 ENVJAVA_HOME/usr/local/jdk
11)WORKDIR
指定工作目錄。用 WORKDIR 指定的工作目錄,會在構(gòu)建鏡像的每一層中都存在。(WORKDIR 指定的工作目錄,必須是提前創(chuàng)建好的)。
語法格式:
WORKDIR<工作目錄路徑>
示例:
FROMbusybox ENVFOO=/bar WORKDIR${FOO}#WORKDIR/bar
12)USER
用于指定執(zhí)行后續(xù)命令的用戶和用戶組,這邊只是切換后續(xù)命令執(zhí)行的用戶(用戶和用戶組必須提前已經(jīng)存在)。
語法格式:
USER<用戶名>[:<用戶組>] USER[: ]
示例:
FROMbusybox RUNgroupadd--system--gid=9999admin&&useradd--system--home-dir/home/admin--uid=9999--gid=adminadmin USERadmin:admin #USER9999:9999
13)EXPOSE
暴露端口 ,僅僅只是聲明端口。
作用:
幫助鏡像使用者理解這個鏡像服務(wù)的守護端口,以方便配置映射。
在運行時使用隨機端口映射時,也就是 docker run -P 時,會自動隨機映射 EXPOSE 的端口。
語法格式:
#默認情況下,EXPOSE假定 TCP。 EXPOSE[ / ...]
示例:
EXPOSE80/TCP443/TCP EXPOSE80443 EXPOSE80/tcp EXPOSE80/udp
14)CMD
類似于 RUN 指令,用于運行程序,但二者運行的時間點不同:CMD 在構(gòu)建鏡像時不會執(zhí)行,在容器運行 時運行。
語法格式:
CMDCMD["<可執(zhí)行文件或命令>"," "," ",...] CMD[" "," ",...]#該寫法是為ENTRYPOINT指令指定的程序提供默認參數(shù)
推薦使用第二種格式,執(zhí)行過程比較明確。第一種格式實際上在運行的過程中也會自動轉(zhuǎn)換成第二種格式運行,并且默認可執(zhí)行文件是 sh。
示例:
CMDcat/etc/profile CMD["/bin/sh","-c","/etc/profile"]
注意:如果 Dockerfile 中如果存在多個 CMD 指令,僅最后一個生效。
15)ENTRYPOINT
類似于 CMD 指令,但其不會被 docker run 的命令行參數(shù)指定的指令所覆蓋,而且這些命令行參數(shù)會被當作參數(shù)送給 ENTRYPOINT 指令指定的程序。但是, 如果運行 docker run 時使用了 --entrypoint 選項,將覆蓋 ENTRYPOINT 指令指定的程序。在 k8s 中 command 也會覆蓋 ENTRYPOINT 指令指定的程序
語法格式:
# exec形式,這是首選形式: ENTRYPOINT["executable","param1","param2"] #外殼形式: ENTRYPOINTcommandparam1param2
示例:
FROMubuntu ENTRYPOINT["top","-b"] #CMD作為ENTRYPOINT參數(shù) CMD["-c"] #與下面的等價 ENTRYPOINT["top","-b-c"] ENTRYPOINTtop-b-c
注意:如果 Dockerfile 中如果存在多個 ENTRYPOINT 指令,僅最后一個生效。
16)HEALTHCHECK
用于指定某個程序或者指令來監(jiān)控 docker 容器服務(wù)的運行狀態(tài)。
語法格式:
HEALTHCHECK[OPTIONS]CMDcommand(通過在容器內(nèi)運行命令檢查容器運行狀況) HEALTHCHECKNONE(禁用從基礎(chǔ)映像繼承的任何運行狀況檢查)
選項CMD有:
--interval=DURATION(默認30s:):間隔,頻率
--timeout=DURATION(默認30s:):超時時間
--start-period=DURATION(默認0s:):為需要時間引導(dǎo)的容器提供初始化時間, 在此期間探測失敗將不計入最大重試次數(shù)。
--retries=N(默認3:):重試次數(shù)
命令的exit status指示容器的運行狀況??赡艿闹禐椋?/p>
0:健康狀態(tài),容器健康且已準備完成。
1:不健康狀態(tài),容器工作不正常。
2:保留,不要使用此退出代碼。
示例:
FROMnginx MAINTAINERSecuritit HEALTHCHECK--interval=5s--timeout=3s CMDcurl-fhttp://localhost/||exit1 CMD["usr/sbin/nginx","-g","daemonoff;"]
17)ONBUILD
ONBUILD 是一個特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等,而這些指令,在當前鏡像構(gòu)建時并不會被執(zhí)行。只有當以當前鏡像為基礎(chǔ)鏡像,去構(gòu)建下一級鏡像的時候才會被執(zhí)行。
語法格式:
ONBUILD<其它指令>
示例:
FROMnode:slim RUNmkdir/app WORKDIR/app ONBUILDCOPY./package.json/app ONBUILDRUN["npm","install"] ONBUILDCOPY./app/ CMD["npm","start"]
18)LABEL
LABEL 指令用來給鏡像添加一些元數(shù)據(jù)(metadata),以鍵值對的形式。用來替代 MAINTAINER。
語法格式:
LABEL= = = ...
示例:比如我們可以添加鏡像的作者
LABELorg.opencontainers.image.authors="runoob"
四、ARG 和 ENV 的區(qū)別
ARG 定義的變量只會存在于鏡像構(gòu)建過程,啟動容器后并不保留這些變量
ENV 定義的變量在啟動容器后仍然保留
五、CMD,ENTRYPOINT,command,args 場景測試
當用戶同時在 kubernetes 中的 yaml 文件中寫了command和args的時候,默認是會覆蓋DockerFile中的命令行和參數(shù),完整的情況分類如下:
1)command 和 args 不存在場景測試
如果 command 和 args 都沒有寫,那么用DockerFile默認的配置。
Dockerfile
FROMcentos COPYtest.sh/ RUNchmod+x/test.sh ###ENTRYPOINT將作為的子命令啟動/bin/sh-c,它不會傳遞參數(shù),要傳遞參數(shù)只能這樣傳參 #ENTRYPOINT["/bin/sh","-c","/test.shENTRYPOINT"] ENTRYPOINT["/test.sh","ENTRYPOINT"] CMD["CMD"]
/tmp/test.sh
#!/bin/bash echo$*
構(gòu)建
dockerbuild-ttest1:v1-fDockerfile.
yaml 編排
cat<test1.yaml apiVersion:apps/v1 kind:Deployment metadata: name:test spec: replicas:1 selector: matchLabels: app:test template: metadata: labels: app:test spec: nodeName:local-168-182-110 containers: -name:test image:test:v1 #command:['/bin/sh','-c','/test.sh'] #args:['args'] EOF
執(zhí)行
kubectlapply-ftest.yaml
2)command 存在,但 args 存在場景測試
如果 command 寫了,但 args 沒有寫,那么 Docker 默認的配置會被忽略而且僅僅執(zhí)行.yaml文件的 command(不帶任何參數(shù)的)。
cat<test2.yaml apiVersion:apps/v1 kind:Deployment metadata: name:test2 spec: replicas:1 selector: matchLabels: app:test2 template: metadata: labels: app:test2 spec: nodeName:local-168-182-110 containers: -name:test2 image:test:v1 #['/bin/sh','-c','/test.sh command','hello'],加了'/bin/sh','-c',也是不能外部傳參,不會輸出hello,只能通過這樣傳參,['/bin/sh','-c','/test.sh command'];CMD里面的參數(shù)會被忽略 command:['/test.sh'] #command帶參數(shù) #command:['/test.sh','command'] #args:['args'] EOF
3)command 不存在,但 args 存在場景測試
如果 command 沒寫,但 args 寫了,那么 Docker 默認配置的 ENTRYPOINT 的命令行會被執(zhí)行,但是調(diào)用的參數(shù)是.yaml中的 args,CMD 的參數(shù)會被覆蓋,但是 ENTRYPOINT 自帶的參數(shù)還是會執(zhí)行的。
cat<test3.yaml apiVersion:apps/v1 kind:Deployment metadata: name:test3 spec: replicas:1 selector: matchLabels: app:test3 template: metadata: labels: app:test3 spec: nodeName:local-168-182-110 containers: -name:test3 image:test:v1 #['/bin/sh','-c','/test.sh command','hello'],加了'/bin/sh','-c',也是不能外部傳參,不會輸出hello,只能通過這樣傳參,['/bin/sh','-c','/test.sh command'];CMD里面的參數(shù)會被忽略 #command:['/test.sh'] #command帶參數(shù) #command:['/test.sh','command'] args:['args'] EOF
4)command 和 args 都存在場景測試
如果如果 command 和 args 都寫了,那么 Docker 默認的配置被忽略,使用.yaml的配置。
cat<test4.yaml apiVersion:apps/v1 kind:Deployment metadata: name:test4 spec: replicas:1 selector: matchLabels: app:test4 template: metadata: labels: app:test4 spec: nodeName:local-168-182-110 containers: -name:test4 image:test:v1 #['/bin/sh','-c','/test.sh command','hello'],加了'/bin/sh','-c',也是不能外部傳參,不會輸出hello,只能通過這樣傳參,['/bin/sh','-c','/test.sh command'];CMD里面的參數(shù)會被忽略 #command:['/test.sh'] #command帶參數(shù),command和args都會帶上 command:['/test.sh','command'] args:['args'] EOF
鏡像構(gòu)建 Dockerfile 的介紹就到這里了,有疑問的小伙伴歡迎給我留言哦!
-
容器
+關(guān)注
關(guān)注
0文章
495瀏覽量
22060 -
鏡像
+關(guān)注
關(guān)注
0文章
164瀏覽量
10707 -
服務(wù)端
+關(guān)注
關(guān)注
0文章
66瀏覽量
7004
原文標題:Docker 鏡像構(gòu)建保姆級入門實戰(zhàn)指南
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論