Dockerfile语法简介(精)
Dockerfile是由一系列命令和參數(shù)構(gòu)成的腳本,一個(gè)Dockerfile里面包含了構(gòu)建整個(gè)image的完整命令。Docker通過docker build執(zhí)行Dockerfile中的一系列命令自動(dòng)構(gòu)建image。
# :代表注釋
一、 FROM
Syntax:
FROM <image>[:<tag> | @<digest>] [AS <name>]-
FROM指定一個(gè)基礎(chǔ)鏡像,且必須為Dockerfile文件開篇的每個(gè)非注釋行,至于image則可以是任何合理存在的image鏡像
-
FROM可以在一個(gè)Dockerfile中出現(xiàn)多次,以便于創(chuàng)建混合的images。如果沒有指定tag,latest將會(huì)被指定為要使用的基礎(chǔ)鏡像版本。
-
AS name,可以給新的構(gòu)建階段賦予名稱。該名稱可用于后續(xù)FROM 和 COPY --from=<name | index>說明可以引用此階段中構(gòu)建的鏡像
?
二、LABEL
為鏡像生成元數(shù)據(jù)標(biāo)簽信息
Syntax:
多個(gè)標(biāo)簽寫成一行,避免在鏡像中額外增加layer
?
三、MAINTAINER
作者信息,寫在FROM后
Syntax:
?
四、COPY
當(dāng)復(fù)制一個(gè)目錄時(shí),并不會(huì)復(fù)制目錄本身,而是會(huì)遞歸復(fù)制其下子目錄 至目標(biāo)目錄下 **Syntax:** ``` COPY data /data/ ```
文件復(fù)制準(zhǔn)則
- <src>必須是build上下言文中的路徑,不能是其父目錄中的文件
- 如果<src>是目錄,則其內(nèi)部文件或子目錄會(huì)被遞歸復(fù)制,但<src>目錄自身不會(huì)被復(fù)制
- 如果指定了多個(gè)<src>,或在<src>中使用了通配符,則<dest>必須是一個(gè)目錄,且必須以/結(jié)尾
- 如果<dest>事先不存在,它將會(huì)被自動(dòng)創(chuàng)建,這包括其父目錄路徑。
?
五、ADD
?
ADD指令類似于COPY指令,ADD支持使用TAR文件和URL路徑
Syntax:
ADD <src>...<dest> ADD ["<src>",..."<dest>"]操作準(zhǔn)則
- 如果<src>為URL且<dest>不以/結(jié)尾,則<src>指定的文件將被下載并直接被創(chuàng)建為<dest>;如果<dest>以/結(jié)尾,則文件名URL指定的文件將被直接下載并保存為<dest>/<filename>
- 如果<src>是一個(gè)本地文件系統(tǒng)上的壓縮格式的tar文件,它將被展開為一個(gè)目錄,其行為類似于"tar -x"命令;然而,通過URL獲取到的tar文件將不會(huì)自動(dòng)展開。
- 如果<src>有多個(gè),或其間接或直接使用了通配符,則<dest>必須是一個(gè)以/結(jié)尾的目錄路徑;如果<dest>不以/結(jié)尾,則其被視作一個(gè)普通文件,<src>內(nèi)容將被直接寫入到<dest>
- 為了讓鏡像盡量小,最好不要使用 ADD 指令從遠(yuǎn)程 URL 獲取包,而是使用 curl 和 wget。這樣你可以在文件提取完之后刪掉不再需要的文件來避免在鏡像中額外添加一層。
示例:
?
六、WORKDIR
?
用于為Dockerfile中所有RUN、CMD、ENTRYPOINT、COPY和ADD指令設(shè)定工作目錄 **Syntax:** ``` WORKDIR?```
在Dockerfile文件中,WORKDIR指令可以出現(xiàn)多次,其路徑也可以為相對(duì)路徑,不過,其是相對(duì)此前一個(gè)WORKDIR指令指定的路徑
另外,WORKDIR也可調(diào)用由ENV指定定義的變量
ex:
WORKDIR /var/logWORKDIR $STATEPATH?
七、RUN
?
接受命令作為參數(shù)并用于創(chuàng)建鏡像,在之前的commit層上形成新的層。 **Syntax:** ``` RUN \(如同執(zhí)行shell命令 /bin/sh -c) RUN ["executable","param1","param2"] ```
- RUN 指令將在當(dāng)前image中執(zhí)行任意合法命令并提交執(zhí)行結(jié)果。命令執(zhí)行提交后,就會(huì)自動(dòng)執(zhí)行Dockerfile中的下一個(gè)指令。
- 分層RUN指令和生成提交符合Docker的核心概念,其中提交很輕量,可以從image將用于Dockerfile中的下一步。
- exec形式使得可以避免shell字符串變化,以及使用不包含指定的shell可執(zhí)行文件的基本image來運(yùn)行RUN命令。
- 在shell形式中,可以使用\(反斜杠)將單個(gè)RUN指令繼續(xù)到下一行。例如: RUN yum install -y \openssl \pcre-devel \zlib
- 第二種語法格式中的參數(shù)是一個(gè)JSON格式的數(shù)組,其中<executable>為要運(yùn)行的命令,后面的<paramN>為傳遞給命令的選項(xiàng)或?qū)?shù);然而,此種格式指定的命令不會(huì)以"/bin/sh -c"來發(fā)起,因此常見的shell操作如變量替換以及通配符(?,*等)替換將不會(huì)進(jìn)行;不過,如果要運(yùn)行的命令依賴于此shell特性的話,可以將其替換為類似下面的格式。
RUN 指令的緩存在下一次構(gòu)建期間不會(huì)自動(dòng)失效。用于諸如:yum repolist 之類的指令的緩存將在下一次構(gòu)建期間被重用。可以通過--no-cache 參數(shù)來使RUN指令的緩存無效,例如: docker build --no-cache
管理命令
某些RUN 命令依賴于使用管道字符( | )將管道輸出到另一個(gè)命令功能
Docker使用 /bin/sh -c 解釋執(zhí)行這些命令,解釋器只評(píng)估管道中最后一個(gè)操作的退出代碼以確定成功。在上面的例子中,只要wc -l 命令成功,即使wget 命令失敗,該構(gòu)建步驟也會(huì)成功并生成新的鏡像。
由于管道中任何階段的錯(cuò)誤而導(dǎo)致命令失敗,請(qǐng)預(yù)先 set -o pipefail && 確保意外錯(cuò)誤可防止構(gòu)建無意中成功。例如:
set -o pipefail : 表示在管道連接的命令序列中,只要有任何一個(gè)命令返回非0值,則整個(gè)管道返回非0值,即使最后一個(gè)命令返回0.
注意:
并非所有的shell都支持 -o pipefail 選項(xiàng)。在這種情況下(例如 dash shell,這是基于Debian的映像上的默認(rèn)shell),請(qǐng)考慮使用exec形式RUN來明確選擇一個(gè)支持該pipefail選項(xiàng)的shell。如:
RUN ["/bin/bash","-c","set -o pipefail && wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html"]?
八、CMD?
類似于RUN指令,CMD指令也可用于運(yùn)行任何命令或應(yīng)用程序,不過,二者的運(yùn)行時(shí)間點(diǎn)不同
- RUN 指令運(yùn)行于映像文件構(gòu)建過程中,而CMD指令運(yùn)行于基于Dockerfile構(gòu)建出的新鏡像文件啟動(dòng)一個(gè)容器時(shí)。
- CMD指令的首要目的在于為啟動(dòng)的容器指定默認(rèn)要運(yùn)行的程序,且其運(yùn)行結(jié)束后,容器也將終止;不過,CMD指定的命令其可以被docker run的命令行選項(xiàng)所覆蓋
- 在Dockerfile中可以存在多個(gè)CMD指令,但僅最后一個(gè)生效
Syntax:
CMD <command> //支持命令展開,但是不支持傳遞信號(hào) CMD ["<executable>","<param1>","<param2>"] //相當(dāng)于容器的第一個(gè)命令,可以接受信號(hào) CMD ["param1","param2"] 前兩種語法格式的意義同RUN 第三種則用于為ENTRYPOINT指令提供默認(rèn)參數(shù)CMD會(huì)在啟動(dòng)容器的時(shí)候執(zhí)行,build時(shí)不執(zhí)行,而RUN只是在構(gòu)建鏡像的時(shí)候執(zhí)行,后續(xù)鏡像構(gòu)建完成之后,啟動(dòng)容器就與RUN無關(guān)了。這個(gè)命令就相當(dāng)于在/etc/rc.d/rc.local中寫命令
?
九、ENTRYPOINT
類似CMD指令的功能,用于為容器指定默認(rèn)運(yùn)行程序,從而使得容器像是一具單獨(dú)的可執(zhí)行程序 與CMD不同的是,由ENTRYPOINT啟動(dòng)的程序不會(huì)被docker run命令行指定的參數(shù)所覆蓋,而且,這些命令行參數(shù)會(huì)被當(dāng)作參數(shù)傳遞給ENTRYPOINT指定的程序。不過,docker run 命令的--entrypoint 選項(xiàng)的參數(shù)可覆蓋ENTRYPOINT指令指定的程序
Syntax:
ENTRYPOINT <command> //這種方式能接受shell命令行展開 ENTRYPOINT ["<executable>","param1"] //展開不了,但能接收到信號(hào)docker run命令傳入的命令參數(shù)會(huì)覆蓋CMD指令的內(nèi)容并且附加到ENTRYPOINT命令最后做為其參數(shù)使用。Dockerfile文件中也可以存在多個(gè)ENTRYPOINT指令,但僅有最后一個(gè)會(huì)生效
?
十、EXPOSE
?用來指定端口,使容器內(nèi)的應(yīng)用可以通過端口和外界交互。 **Syntax:** ``` EXPOSE?[...] ```
告訴Docker服務(wù)端容器對(duì)外映射的本地端口,需要在docker run 的時(shí)候使用-p 或者 -P 選項(xiàng)生效。
EXPOSE 80/tcp?
十一、ENV
ENV指令可以用于docker容器設(shè)置環(huán)境變量 **Syntax:** ``` ENV?ENV?=?... ```
指定一個(gè)環(huán)境變量,會(huì)被后續(xù)RUN指令使用,并在容器運(yùn)行時(shí)保留。
ENV設(shè)置的環(huán)境變量,可以使用 docker inspect 命令來查看。同時(shí)還可以使用 docker run --env <key>=<value>來修改環(huán)境變量
?
十二、USER
用于指定運(yùn)行image時(shí)的或運(yùn)行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序時(shí)的用戶名或UID 默認(rèn)情況下,container的運(yùn)行身份為root用戶 **Syntax:** ``` USER?|?``` 需要注意的是,\可以為任意數(shù)字,但實(shí)踐中其必須為/etc/passwd中某用戶的有效UID,否則,docker run命令將運(yùn)行失敗
?
十三、ONBUILD
用于在Dockerfile中定義一個(gè)觸發(fā)器 Dockerfile用于build映像文件,此映像文件亦可作為base image被另一個(gè)Dockerfile用作FROM指令的參數(shù),并以之構(gòu)建新的映像文件 在后的這個(gè)Dockerfile中的FROM指令在build過程中被執(zhí)行時(shí),將會(huì)“觸發(fā)”創(chuàng)建其base image的Dockerfile文件中的ONBUILD指令定義的觸發(fā)器
Syntax:
ONBUILD <INSTRUCTION>注意:
盡管任何指令都可注冊(cè)成為觸發(fā)器指令,但ONBUILD不能自我嵌套,且不會(huì)觸發(fā)FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile構(gòu)建的鏡像應(yīng)該使用特殊的標(biāo)簽,例如ruby:2.0-onbuild
在ONBUILD指令中使用ADD或COPY指令應(yīng)該格外小心,因?yàn)樾聵?gòu)建過程和上下文在缺少指定的源文件時(shí)會(huì)失敗。
?
十四、HEALTHCHECK
Docker 1.12版本后引入的判斷容器狀態(tài)是否正常
Syntax:
HEALTHCHECK [OPTION] CMD <command> //設(shè)置檢查容器健康狀況的命令 HEALTHCHECK NONE //如果基礎(chǔ)鏡像有健康檢查指令,使用這行可屏蔽掉其健康檢查指令在沒HEALTHCHECK指令前,Docker只能通過容器內(nèi)主進(jìn)程是否退出來判斷容器是否狀態(tài)異常。很多情況下這沒問題,但是如果程序進(jìn)入死鎖狀態(tài),或者死循環(huán)狀態(tài),應(yīng)用進(jìn)程并不退出,但是該容器已經(jīng)無法提供服務(wù)了。雖然后端的程序可以通過前端的檢測(cè)工具來檢查狀態(tài)信息。但是最前端的服務(wù)就需要本身的檢測(cè)機(jī)制加上監(jiān)控,就可以做到出現(xiàn)問題解決問題。
當(dāng)在一個(gè)鏡像指定了 HEALTHCHECK 指令后,用其啟動(dòng)容器,初始狀態(tài)會(huì)為 starting,在 HEALTHCHECK 指令檢查成功后變?yōu)?healthy,如果連續(xù)一定次數(shù)失敗,則會(huì)變?yōu)?unhealthy。
HEALTHCHECK支持下列選項(xiàng):
- --interval=<間隔> : 兩次健康檢查間隔,默認(rèn)30秒
- --timeout=<時(shí)長> : 健康檢查命令運(yùn)行超時(shí)時(shí)間,如果超過這個(gè)時(shí)間,本次健康檢查就被視為失敗,默認(rèn)為30秒
- --retries=<次數(shù)> :當(dāng)連續(xù)失敗指定次數(shù)后,則將容器狀態(tài)視為unhealthy,默認(rèn)3次。
和CMD、ENTRYPOINT一樣,HEALTHCHECK只可以出現(xiàn)一次,如果寫了多個(gè),只有最后一個(gè)生效。CMD 后面的命令也分為shell和exec格式。命令的返回值決定了該次檢查的成功與否:?0表示成功;1表示失敗;2保留。
ex:
HEALTHCHECK --interval=5s --timeout=3s \CMD curl -fs http://localhost/ || exit 1?
總結(jié)
以上是生活随笔為你收集整理的Dockerfile语法简介(精)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python类及其方法
- 下一篇: Python shutil文件操作、文件