dockerfile其實就是記錄'火箭發射'步驟的文件,它記載了從一個鏡像建立另外一個新鏡像的步驟。撰寫好Dockerfile文件以後,咱們就能夠垂手可得的使用docker build
命令來建立鏡像了。java
Dockerfile 是一個文本文件,其內包含了一條條的指令(Instruction),每一條指令構建一層,所以每一條指令的內容,就是描述該層應當如何構建。有了 Dockerfile,當咱們須要定製本身額外的需求時,只需在 Dockerfile 上添加或者修改指令,從新生成 image 便可,省去了敲命令的麻煩。python
下面是一個dockerfile文件的例子:linux
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"] 複製代碼
部分 | 命令 |
---|---|
基礎鏡像信息 | FROM |
維護者信息 | MAINTAINER |
鏡像操做指令 | RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等 |
容器啓動時執行指令 | CMD、ENTRYPOINT |
FROM
構建的鏡像設置基礎鏡像golang
FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]
複製代碼
FROM
指令初始化新的構建階段,併爲後續指令設置基礎鏡像,e.g: FROM openjdk:8-jdk-alpine
。所以,Dockerfile文件必須以FROM
指令開頭。 而指定的鏡像可使任何有效的鏡像(推薦使用公共倉庫的鏡像,由於拉取更爲容易)。docker
ARG
是惟一一個能夠用於FROM
以前的指令。ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras 複製代碼
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 名稱
來指定一個名稱給後續階段的FROM
和COPY --from=<name|index>
使用。RUN
在鏡像的構建過程當中執行特定的命令,並生成一箇中間鏡像。好比安裝一些軟件、配置一些基礎環境,可以使用\來換行。shell
RUN <command> (shell格式)
RUN ["executable", "param1", "param2"] (exec格式)
複製代碼
要注意的是,executable是命令,後面的param是參數
採用exec格式指令將會被解析成json格式因此不能使用單引號,而且使用反斜槓也是必需要轉移的,這在windows上尤其重要。json
CMD
指定容器運行時的默認參數。ubuntu
CMD ["executable","param1","param2"](exec格式,首選)
CMD ["param1","param2"](給ENTRYPOINT提供默認參數)
CMD command param1 param2(shell格式)
複製代碼
注意:
RUN
是在構建的時候執行,並生成一個新的鏡像,CMD
在構建時不進行任何操做,在容器運行的時候執行。
若是CMD
用於爲ENTRYPOINT
指令提供缺省參數,那麼CMD
和ENTRYPOINT
指令都應該使用JSON數組格式。windows
LABEL
給構建的鏡像打標籤。數組
LABEL <key>=<value> <key>=<value> <key>=<value> ...
複製代碼
標籤是鍵值對格式,要在標籤中包含空格則需轉義或用引號"
括起來。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." 複製代碼
一個鏡像能夠有多個標籤,若是基礎鏡像也有標籤則繼承,名字相同的話則會覆蓋。若是使用多個標籤,建議合併成一個標籤指令,若是使用多個標籤指令, 則每一個標籤指令都會生成一個圖層,這會致使鏡像生成效率低下。舉個栗子:
LABEL multi.label1="value1" multi.label2="value2" other="value3" 複製代碼
也能夠寫成:
LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3" 複製代碼
MAINTAINER(已棄用)
設置做者信息。
MAINTAINER <name>
複製代碼
LABEL
比MAINTAINER
更靈活,推薦使用LABEL
,棄用MAINTAINER
。
LABEL maintainer="makise_kurisuu@outlook.jp"
複製代碼
EXPOSE
爲構建的鏡像設置監聽端口。
EXPOSE <port> [<port>/<protocol>...]
複製代碼
EXPOSE
指令讓docker容器在運行的時候監聽指定的端口,能夠指定端口是upd仍是tcp協議,若是沒有指定則默認tcp協議。
EXPOSE
指令並不會發佈端口,若是發佈端口,則須要在docker run時使用-p來發布和映射一個或多個容器端口、或者使用-P來發布全部公開的端口 並將它們映射到高階端口。
ENV
在構建的鏡像中設置環境變量,在後續的Dockerfile指令中能夠直接使用,也能夠固化在鏡像裏,在容器運行時仍然有效。 ENV
指令有兩種格式:
"
括起來。ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy
複製代碼
或者
ENV myName="John Doe" myDog=Rex\ The\ Dog \
myCat=fluffy
複製代碼
推薦使用第二種,一樣的這樣能減小圖層提升效率。
注意:能夠在容器運行時指定環境變量,替換鏡像中的已有變量,
docker run --env <key>=<value>
。
使用ENV可能會對後續的Dockerfile指令形成影響,若是隻須要對一條指令設置環境變量,可使用這種方式:RUN <key>=<value> <command>
ADD
構建鏡像時,複製上下文中的文件到鏡像內。
ADD <src>... <dest>
ADD ["<src>",... "<dest>"](路徑包含空格的必須使用這種格式)
複製代碼
<src>
能夠是文件、目錄,也能夠是文件URL。可使用模糊匹配(wildcards,相似shell的匹配),能夠指定多個<src>
,必須是在上下文目錄和子目錄中, 沒法添加../a.txt
這樣的文件。若是<src>
是個目錄,則複製的是目錄下的全部內容,但不包括該目錄。若是<src>
是個可被docker識別的壓縮包, docker會以tar -x的方式解壓後將內容複製到<desct>
。<dest>
能夠是絕對路徑,也能夠是相對WORKDIR目錄的相對路徑。 全部文件的UID和GID都是0。
若是docker發現文件內容被改變,則接下來的指令都不會再使用緩存。
關於複製文件時須要處理的/,基本跟正常的copy一致。
COPY
將主機的文件複製到鏡像內,若是目的位置不存在,Docker會自動建立全部須要的目錄結構,可是它只是單純的複製,並不會去作文件提取和解壓工做。
COPY <src>... <dest>
COPY ["<src>",... "<dest>"](路徑包含空格的必須使用這種格式)
複製代碼
注意:須要複製的目錄必定要放在Dockerfile文件的同級目錄下。
由於構建環境將會上傳到Docker守護進程,而複製是在Docker守護進程中進行的。任何位於構建環境以外的東西都是不可用的。 COPY指令的目的的位置則必須是容器內部的一個絕對路徑。
COPY指令
ENTRYPOINT
指定鏡像的執行程序。ENTRYPOINT
指令有兩種格式:
ENTRYPOINT ["executable", "param1", "param2"] (執行格式,首選)
ENTRYPOINT command param1 param2 (shell格式)
複製代碼
詳細參考:ENTRYPOINT指令
CMD
和ENTRYPOINT
至少得使用一個。ENTRYPOINT
應該被當作docker的可執行程序,CMD應該被當作ENTRYPOINT
的默認參數。 docker run <image> <arg1> <arg2> ...
會把以後的參數傳遞給ENTRYPOINT
,覆蓋CMD指定的參數。能夠用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
指定鏡像內的目錄爲數據卷。
VOLUME ["/data"]
複製代碼
在容器運行的時候,docker會把鏡像中的數據卷的內容複製到容器的數據卷中去。 若是在接下來的Dockerfile指令中,修改了數據卷中的內容,則修改無效。
USER
爲接下來的Dockerfile指令指定用戶。受影響的指令有:RUN
、CMD
、ENTRYPOINT
。
USER <user>[:<group>] or
USER <UID>[:<GID>]
複製代碼
注意:當用戶沒有主要組時,鏡像(或下一條指令)將與該root組一塊兒運行。
WORKDIR
爲接下來的Dockerfile指令指定當前工做目錄,可屢次使用,若是使用的是相對路徑,則相對的是上一個工做目錄,相似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
設置的環境變量,只能使用Dockerfile中顯式設置的環境變量。例如:
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME RUN pwd 複製代碼
此Dockerfile中pwd
指令將輸出 /path/$DIRNAME
。
ARG
指定用戶在docker build --build-arg <varname>=<value>
時可使用的參數。
ARG <name>[=<default value>]
複製代碼
若是用戶指定了未在Dockerfile中定義的構建參數,則構建會輸出警告。
[Warning] One or more build-args [foo] were not consumed.
複製代碼
構建參數在定義的時候生效而不是在使用的時候。以下面第三行開始的user纔是用戶構建參數傳遞過來的user:
FROM busybox
# 此處獲取不到用戶傳來的user
USER ${user:-some_user}
ARG user
USER $user
複製代碼
您可使用ARG
或ENV
指令指定RUN
指令可用的變量。使用ENV
指令定義的環境變量始終覆蓋同名的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還內置了一批構建參數,能夠不用在Dockerfile中聲明:HTTP_PROXY
、http_proxy
、HTTPS_PROXY
、https_proxy
、FTP_PROXY
、 ftp_proxy
、NO_PROXY
、no_proxy
注意:在使用構建參數(而不是在構建參數定義的時候)的指令中,若是構建參數的值發生了變化,會致使該指令發生變化,會從新尋找緩存。
ONBUILD
向鏡像中添加一個觸發器,當以該鏡像爲基礎鏡像再次構建新的鏡像時,會觸發執行其中的指令。
ONBUILD [INSTRUCTION]
複製代碼
好比咱們生成的鏡像是用來部署Python代碼的,可是由於有多個項目可能會複用該鏡像。你能夠這樣使用:
[...]
# 在下一次以此鏡像爲base image的構建中,執行ADD . /app/src,將項目代目添加到新鏡像中去
ONBUILD ADD . /app/src # 而且build Python代碼
ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
複製代碼
不容許
ONBUILD
使用連接指令ONBUILD ONBUILD
。
ONBUILD
只會繼承給子節點的鏡像,不會再繼承給孫子節點。
ONBUILD
不會觸發FROM
、MAINTAINER
指令。
STOPSIGNAL
觸發系統信號。
STOPSIGNAL signal
複製代碼
STOPSIGNAL
指令設置將發送到容器以退出的系統調用信號。此信號能夠是與內核的SysCall表中的位置匹配的有效無符號數字(例如9),也能夠是格式爲SIGNAME的信號名稱(例如SIGKILL)。
HEALTHCHECK
增長自定義的心跳檢測功能,屢次使用只有最後一次有效。格式:
HEALTHCHECK [OPTIONS] CMD command (經過在容器內運行命令來檢查容器運行情況)
HEALTHCHECK NONE (禁用從基礎映像繼承的任何運行情況檢查)
複製代碼
可選的OPTION:
--interval=DURATION
(檢測間隔,默認值:30s)--timeout=DURATION
(命令超時時間,默認值:30s)--start-period=DURATION
(初始化後開始檢查時間,默認值:0s)--retries=N
(連續N次失敗後標記爲不健康,默認值:3次)Start Period爲須要時間引導的容器提供初始化時間。在此期間的探測失敗將不計入最大重試次數。可是,若是運行情況檢查在開始期間成功,則容器將被視爲已啓動,而且全部連續失敗將計入最大重試次數。
<command>
能夠是shell腳本,也能夠是exec格式的json數組。 docker以<command>
的退出狀態碼來區分容器是否健康,這一點同shell一致:
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1 複製代碼
你可使用docker inspect
命令查看健康狀態。
當容器的運行情況發生更改時,將生成帶有新狀態的health_status事件。
SHELL
更改後續的Dockerfile指令中所使用的shell。默認的shell是["bin/sh", "-c"]
。可屢次使用,每次都只改變後續指令。
SHELL ["executable", "parameters"] 複製代碼