什么是Dockerfile
dockerfile其實就是記錄'火箭發(fā)射'步驟的文件,它記載了從一個鏡像創(chuàng)建另一個新鏡像的步驟闯团。撰寫好Dockerfile文件之后,我們就可以輕而易舉的使用docker build
命令來創(chuàng)建鏡像了伐谈。
Dockerfile 是一個文本文件秃流,其內(nèi)包含了一條條的指令(Instruction),每一條指令構(gòu)建一層设哗,因此每一條指令的內(nèi)容唱捣,就是描述該層應(yīng)當(dāng)如何構(gòu)建。有了 Dockerfile网梢,當(dāng)我們需要定制自己額外的需求時震缭,只需在 Dockerfile 上添加或者修改指令,重新生成 image 即可战虏,省去了敲命令的麻煩拣宰。
下面是一個dockerfile文件的例子:
FROM openjdk:8-jdk-alpine
MAINTAINER Kurisu "makise_kurisuu@outlook.jp"
LABEL maintainer="makise_kurisuu@outlook.jp"
VOLUME /tmp
ARG JAR_FILE=target/alice-server.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
Dockerfile 的組成部分
部分 | 命令 |
---|---|
基礎(chǔ)鏡像信息 | FROM |
維護者信息 | MAINTAINER |
鏡像操作指令 | RUN、COPY烦感、ADD倾鲫、EXPOSE欧引、WORKDIR舶衬、ONBUILD耿导、USER、VOLUME等 |
容器啟動時執(zhí)行指令 | CMD回懦、ENTRYPOINT |
DockerFile命令詳解
-
FROM
構(gòu)建的鏡像設(shè)置基礎(chǔ)鏡像FROM <image> [AS <name>] FROM <image>[:<tag>] [AS <name>] FROM <image>[@<digest>] [AS <name>]
FROM
指令初始化新的構(gòu)建階段气笙,并為后續(xù)指令設(shè)置基礎(chǔ)鏡像,e.g:FROM openjdk:8-jdk-alpine
怯晕。因此潜圃,Dockerfile文件必須以FROM
指令開頭。
而指定的鏡像可以使任何有效的鏡像(推薦使用公共倉庫的鏡像舟茶,因為拉取更為容易)谭期。- 在Dockerfile文件中
ARG
是唯一一個可以用于FROM
之前的指令。
ARG CODE_VERSION=latest FROM base:${CODE_VERSION} CMD /code/run-app FROM extras:${CODE_VERSION} CMD /code/run-extras
- 一個Dockerfile文件可以有多個FROM指令吧凉,來創(chuàng)建多個鏡像或者使用其中一個階段作為另一個階段的依賴項隧出。以最后一個鏡像的ID為輸出值。e.g:
FROM golang:1.10.3 COPY server.go /build/ WORKDIR /build RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server ENTRYPOINT ["/build/server"]
- 我們可以通過在
FROM
指令中添加AS 名稱
來指定一個名稱給后續(xù)階段的FROM
和COPY --from=<name|index>
使用阀捅。 - tag和digest是可選的胀瞪,如果不提供則使用latest。
- 在Dockerfile文件中
-
RUN
在鏡像的構(gòu)建過程中執(zhí)行特定的命令,并生成一個中間鏡像凄诞。比如安裝一些軟件圆雁、配置一些基礎(chǔ)環(huán)境,可使用\來換行帆谍。RUN <command> (shell格式) RUN ["executable", "param1", "param2"] (exec格式)
要注意的是伪朽,executable是命令,后面的param是參數(shù)
采用exec格式指令將會被解析成json格式所以不能使用單引號汛蝙,并且使用反斜杠也是必須要轉(zhuǎn)移的烈涮,這在windows上尤為重要。 -
CMD
指定容器運行時的默認參數(shù)窖剑。CMD ["executable","param1","param2"](exec格式跃脊,首選) CMD ["param1","param2"](給ENTRYPOINT提供默認參數(shù)) CMD command param1 param2(shell格式)
注意:
RUN
是在構(gòu)建的時候執(zhí)行,并生成一個新的鏡像苛吱,CMD
在構(gòu)建時不進行任何操作,在容器運行的時候執(zhí)行器瘪。
如果CMD
用于為ENTRYPOINT
指令提供缺省參數(shù)翠储,那么CMD
和ENTRYPOINT
指令都應(yīng)該使用JSON數(shù)組格式。 -
LABEL
給構(gòu)建的鏡像打標(biāo)簽橡疼。LABEL <key>=<value> <key>=<value> <key>=<value> ...
標(biāo)簽是鍵值對格式,要在標(biāo)簽中包含空格則需轉(zhuǎn)義或用引號
"
括起來援所。e.g:LABEL "com.example.vendor"="ACME Incorporated" LABEL com.example.label-with-value="foo" LABEL version="1.0" LABEL description="This text illustrates \ that label-values can span multiple lines."
一個鏡像可以有多個標(biāo)簽,如果基礎(chǔ)鏡像也有標(biāo)簽則繼承欣除,名字相同的話則會覆蓋住拭。如果使用多個標(biāo)簽,建議合并成一個標(biāo)簽指令历帚,如果使用多個標(biāo)簽指令滔岳,
則每個標(biāo)簽指令都會生成一個圖層,這會導(dǎo)致鏡像生成效率低下挽牢。舉個栗子:LABEL multi.label1="value1" multi.label2="value2" other="value3"
也可以寫成:
LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
-
MAINTAINER(已棄用)
設(shè)置作者信息谱煤。MAINTAINER <name>
LABEL
比MAINTAINER
更靈活,推薦使用LABEL
禽拔,棄用MAINTAINER
刘离。LABEL maintainer="makise_kurisuu@outlook.jp"
-
EXPOSE
為構(gòu)建的鏡像設(shè)置監(jiān)聽端口。EXPOSE <port> [<port>/<protocol>...]
EXPOSE
指令讓docker容器在運行的時候監(jiān)聽指定的端口睹栖,可以指定端口是upd還是tcp協(xié)議硫惕,如果沒有指定則默認tcp協(xié)議。
EXPOSE
指令并不會發(fā)布端口野来,如果發(fā)布端口恼除,則需要在docker run時使用-p來發(fā)布和映射一個或多個容器端口、或者使用-P來發(fā)布所有公開的端口
并將它們映射到高階端口梁只。 -
ENV
在構(gòu)建的鏡像中設(shè)置環(huán)境變量缚柳,在后續(xù)的Dockerfile指令中可以直接使用埃脏,也可以固化在鏡像里,在容器運行時仍然有效秋忙。
ENV
指令有兩種格式:- ENV <key> <value>:把第一個空格之后的所有值都當(dāng)做<key>的值彩掐,無法在一行內(nèi)設(shè)定多個環(huán)境變量。
- ENV <key>=<value> ...:可以設(shè)置多個環(huán)境變量灰追,如果<value>中存在空格堵幽,需要轉(zhuǎn)義或用引號
"
括起來。
ENV myName John Doe ENV myDog Rex The Dog ENV myCat fluffy
或者
ENV myName="John Doe" myDog=Rex\ The\ Dog \ myCat=fluffy
推薦使用第二種弹澎,同樣的這樣能減少圖層提高效率朴下。
注意:可以在容器運行時指定環(huán)境變量,替換鏡像中的已有變量苦蒿,
docker run --env <key>=<value>
殴胧。
使用ENV可能會對后續(xù)的Dockerfile指令造成影響,如果只需要對一條指令設(shè)置環(huán)境變量佩迟,可以使用這種方式:RUN <key>=<value> <command>
-
ADD
構(gòu)建鏡像時团滥,復(fù)制上下文中的文件到鏡像內(nèi)。ADD <src>... <dest> ADD ["<src>",... "<dest>"](路徑包含空格的必須使用這種格式)
<src>
可以是文件报强、目錄灸姊,也可以是文件URL”龋可以使用模糊匹配(wildcards力惯,類似shell的匹配),可以指定多個<src>
召嘶,必須是在上下文目錄和子目錄中父晶,
無法添加../a.txt
這樣的文件。如果<src>
是個目錄弄跌,則復(fù)制的是目錄下的所有內(nèi)容诱建,但不包括該目錄。如果<src>
是個可被docker識別的壓縮包碟绑,
docker會以tar -x的方式解壓后將內(nèi)容復(fù)制到<desct>
俺猿。<dest>
可以是絕對路徑,也可以是相對WORKDIR目錄的相對路徑格仲。
所有文件的UID和GID都是0押袍。如果docker發(fā)現(xiàn)文件內(nèi)容被改變,則接下來的指令都不會再使用緩存凯肋。
關(guān)于復(fù)制文件時需要處理的/谊惭,基本跟正常的copy一致。 -
COPY
將主機的文件復(fù)制到鏡像內(nèi),如果目的位置不存在圈盔,Docker會自動創(chuàng)建所有需要的目錄結(jié)構(gòu)豹芯,但是它只是單純的復(fù)制,并不會去做文件提取和解壓工作驱敲。COPY <src>... <dest> COPY ["<src>",... "<dest>"](路徑包含空格的必須使用這種格式)
注意:需要復(fù)制的目錄一定要放在Dockerfile文件的同級目錄下铁蹈。
因為構(gòu)建環(huán)境將會上傳到Docker守護進程,而復(fù)制是在Docker守護進程中進行的众眨。任何位于構(gòu)建環(huán)境之外的東西都是不可用的握牧。
COPY指令的目的的位置則必須是容器內(nèi)部的一個絕對路徑。
COPY指令 -
ENTRYPOINT
指定鏡像的執(zhí)行程序娩梨。ENTRYPOINT
指令有兩種格式:ENTRYPOINT ["executable", "param1", "param2"] (執(zhí)行格式沿腰,首選) ENTRYPOINT command param1 param2 (shell格式)
詳細參考:ENTRYPOINT指令
CMD
和ENTRYPOINT
至少得使用一個。ENTRYPOINT
應(yīng)該被當(dāng)做docker的可執(zhí)行程序狈定,CMD應(yīng)該被當(dāng)做ENTRYPOINT
的默認參數(shù)颂龙。
docker run <image> <arg1> <arg2> ...
會把之后的參數(shù)傳遞給ENTRYPOINT
,覆蓋CMD指定的參數(shù)纽什±逋校可以用docker run --entrypoint
來重置默認的ENTRYPOINT
。— No ENTRYPOINT ENTRYPOINT exec_entry p1_entry ENTRYPOINT ["exec_entry", "p1_entry"] No CMD error, not allowed /bin/sh -c exec_entry p1_entry exec_entry p1_entry CMD ["exec_cmd", "p1_cmd"] exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry exec_cmd p1_cmd CMD ["p1_cmd", "p2_cmd"] p1_cmd p2_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry p1_cmd p2_cmd CMD exec_cmd p1_cmd CMD exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd -
VOLUME
指定鏡像內(nèi)的目錄為數(shù)據(jù)卷稿湿。VOLUME ["/data"]
在容器運行的時候,docker會把鏡像中的數(shù)據(jù)卷的內(nèi)容復(fù)制到容器的數(shù)據(jù)卷中去押赊。
如果在接下來的Dockerfile指令中饺藤,修改了數(shù)據(jù)卷中的內(nèi)容,則修改無效流礁。 -
USER
為接下來的Dockerfile指令指定用戶涕俗。受影響的指令有:RUN
、CMD
神帅、ENTRYPOINT
再姑。USER <user>[:<group>] or USER <UID>[:<GID>]
注意:當(dāng)用戶沒有主要組時,鏡像(或下一條指令)將與該root組一起運行找御。
-
WORKDIR
為接下來的Dockerfile指令指定當(dāng)前工作目錄元镀,可多次使用,如果使用的是相對路徑霎桅,則相對的是上一個工作目錄栖疑,類似shell中的cd命令。WORKDIR /path/to/workdir
受影響的指令有:
RUN
滔驶、CMD
遇革、ENTRYPOINT
、COPY
和ADD
。
可以在Dockerfile中多次使用WORKDIR
指令萝快。如果提供了相對路徑锻霎,則它將相對于上一個WORKDIR
指令的路徑。例如:WORKDIR /a WORKDIR b WORKDIR c RUN pwd
此Dockerfile中
pwd
指令將輸出/a/b/c.
揪漩。
WORKDIR
指令可以解析之前使用ENV
設(shè)置的環(huán)境變量旋恼,只能使用Dockerfile中顯式設(shè)置的環(huán)境變量。例如:ENV DIRPATH /path WORKDIR $DIRPATH/$DIRNAME RUN pwd
此Dockerfile中
pwd
指令將輸出/path/$DIRNAME
氢拥。 -
ARG
指定用戶在docker build --build-arg <varname>=<value>
時可以使用的參數(shù)蚌铜。ARG <name>[=<default value>]
如果用戶指定了未在Dockerfile中定義的構(gòu)建參數(shù),則構(gòu)建會輸出警告嫩海。
[Warning] One or more build-args [foo] were not consumed.
構(gòu)建參數(shù)在定義的時候生效而不是在使用的時候冬殃。如下面第三行開始的user才是用戶構(gòu)建參數(shù)傳遞過來的user:
FROM busybox # 此處獲取不到用戶傳來的user USER ${user:-some_user} ARG user USER $user
您可以使用
ARG
或ENV
指令指定RUN
指令可用的變量。使用ENV
指令定義的環(huán)境變量始終覆蓋同名的ARG
指令叁怪。FROM ubuntu ARG CONT_IMG_VER ENV CONT_IMG_VER v1.0.0 # 始終是v1.0.0 RUN echo $CONT_IMG_VER
正確的用法:
FROM ubuntu ARG CONT_IMG_VER ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0} RUN echo $CONT_IMG_VER
要在多個階段中使用arg审葬,每個階段都必須包含該ARG指令。
FROM busybox ARG SETTINGS RUN ./run/setup $SETTINGS FROM busybox ARG SETTINGS RUN ./run/other $SETTINGS
此外docker還內(nèi)置了一批構(gòu)建參數(shù)奕谭,可以不用在Dockerfile中聲明:
HTTP_PROXY
涣觉、http_proxy
、HTTPS_PROXY
血柳、https_proxy
官册、FTP_PROXY
、
ftp_proxy
难捌、NO_PROXY
膝宁、no_proxy
注意:在使用構(gòu)建參數(shù)(而不是在構(gòu)建參數(shù)定義的時候)的指令中,如果構(gòu)建參數(shù)的值發(fā)生了變化根吁,會導(dǎo)致該指令發(fā)生變化员淫,會重新尋找緩存。
-
ONBUILD
向鏡像中添加一個觸發(fā)器击敌,當(dāng)以該鏡像為基礎(chǔ)鏡像再次構(gòu)建新的鏡像時介返,會觸發(fā)執(zhí)行其中的指令。ONBUILD [INSTRUCTION]
比如我們生成的鏡像是用來部署Python代碼的沃斤,但是因為有多個項目可能會復(fù)用該鏡像圣蝎。你可以這樣使用:
[...] # 在下一次以此鏡像為base image的構(gòu)建中,執(zhí)行ADD . /app/src衡瓶,將項目代目添加到新鏡像中去 ONBUILD ADD . /app/src # 并且build Python代碼 ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
不允許
ONBUILD
使用鏈接指令ONBUILD ONBUILD
捅彻。
ONBUILD
只會繼承給子節(jié)點的鏡像,不會再繼承給孫子節(jié)點鞍陨。
ONBUILD
不會觸發(fā)FROM
步淹、MAINTAINER
指令从隆。 -
STOPSIGNAL
觸發(fā)系統(tǒng)信號。STOPSIGNAL signal
STOPSIGNAL
指令設(shè)置將發(fā)送到容器以退出的系統(tǒng)調(diào)用信號缭裆。此信號可以是與內(nèi)核的SysCall表中的位置匹配的有效無符號數(shù)字(例如9)键闺,也可以是格式為SIGNAME的信號名稱(例如SIGKILL)。 -
HEALTHCHECK
增加自定義的心跳檢測功能澈驼,多次使用只有最后一次有效辛燥。格式:HEALTHCHECK [OPTIONS] CMD command (通過在容器內(nèi)運行命令來檢查容器運行狀況) HEALTHCHECK NONE (禁用從基礎(chǔ)映像繼承的任何運行狀況檢查)
可選的OPTION:
-
--interval=DURATION
(檢測間隔,默認值:30s) -
--timeout=DURATION
(命令超時時間缝其,默認值:30s) -
--start-period=DURATION
(初始化后開始檢查時間挎塌,默認值:0s) -
--retries=N
(連續(xù)N次失敗后標(biāo)記為不健康,默認值:3次)
Start Period為需要時間引導(dǎo)的容器提供初始化時間内边。在此期間的探測失敗將不計入最大重試次數(shù)榴都。但是,如果運行狀況檢查在開始期間成功漠其,則容器將被視為已啟動嘴高,并且所有連續(xù)失敗將計入最大重試次數(shù)。
<command>
可以是shell腳本和屎,也可以是exec格式的json數(shù)組拴驮。
docker以<command>
的退出狀態(tài)碼來區(qū)分容器是否健康,這一點同shell一致:- 0:命令返回成功柴信,容器健康
- 1:命令返回失敗套啤,容器不健康
- 2:保留狀態(tài)碼,不要使用
舉個栗子:每5分鐘檢測本地網(wǎng)頁是否可訪問随常,超時設(shè)為3秒:
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1
你可以使用
docker inspect
命令查看健康狀態(tài)潜沦。
當(dāng)容器的運行狀況發(fā)生更改時,將生成帶有新狀態(tài)的health_status事件线罕。 -
-
SHELL
更改后續(xù)的Dockerfile指令中所使用的shell。默認的shell是["bin/sh", "-c"]
窃判〕ィ可多次使用,每次都只改變后續(xù)指令袄琳。SHELL ["executable", "parameters"]