Docker 能夠經過 Dockerfile 的內容來自動構建鏡像。Dockerfile 是一個包含建立鏡像全部命令的文本文件,經過docker build命令能夠根據 Dockerfile 的內容構建鏡像,在介紹如何構建以前先介紹下 Dockerfile 的基本語法結構。python
Dockerfile 有如下指令選項: FROM、LABEL、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD
用法:linux
FROM <image>
或者golang
FROM <image>:<tag>
或者docker
FROM <image>@<digest>
FROM指令設置基本鏡像用於後續指令;若是本地沒有指定的鏡像,則會自動從 Docker 的公共庫 pull 鏡像下來。shell
RUN 指令有兩種形式:apache
RUN <command>
(shell 形式,命令在shell中運行,在linux默認是/bin/sh -c,在Windows默認是cmd /S /C)RUN ["executable", "param1", "param2"]
(exec 形式)每條RUN指令將在當前鏡像基礎上執行指定命令,並提交爲新的鏡像,後續的指令都以以前RUN提交後的鏡像爲基礎,鏡像是分層的,能夠經過一個鏡像的任何一個歷史提交點來建立,相似源碼的版本控制。json
exec 方式會被解析爲一個 JSON 數組,因此必須使用雙引號而不是單引號。ubuntu
exec 可使用不一樣的shell,而不是/bin/sh,例如:
RUN ["/bin/bash", "-c", "echo hello"]
數組
RUN產生的緩存在下一次構建的時候是不會失效的,會被重用,可使用--no-cache選項,即docker build --no-cache
,如此便不會緩存。緩存
CMD 指令有三種形式:
CMD ["executable","param1","param2"]
(exec 形式,首選的形式)CMD ["param1","param2"]
(做爲 ENTRYPOINT 指令的默認參數)CMD command param1 param2
(shell 形式)CMD指定在 Dockerfile 中只能使用一次,若是有多個,則只有最後一個會生效。
CMD的目的是爲了在啓動容器時提供一個默認的命令執行選項。若是用戶啓動容器時指定了運行的命令,則會覆蓋掉CMD指定的命令。
若是CMD 指令提供默認的參數給ENTRYPOINT 指令,CMD和ENTRYPOINT指令都規定使用json格式
另外注意不要弄混如下的概念:
CMD 在build時不執行,在啓動容器的時候執行,而RUN只是在build的時候執行,後續鏡像構建完成以後,啓動容器就與RUN無關了
LABEL <key>=<value> <key>=<value> <key>=<value> ...
LABEL指令用於添加鏡像的元資料,LABEL 是一對key-value值。例如:
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,要指定多個標籤,Docker建議在可能的狀況下將標籤組合到單個LABEL指令中,由於每個LABEL指令都會產生一個新的層。若是想設置多個標籤,能夠用以下方法:
LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
LABEL中若是key已存在,後面添加相同的key,則使用新的value
MAINTAINER <name>
MAINTAINER用戶設置鏡像的做者。LABEL指令能夠更靈活的代替,例如:
LABEL maintainer "SvenDowideit@home.org.au"
EXPOSE <port> [<port>...]
告訴 Docker 服務端容器對外映射的本地端口,須要在 docker run 的時候使用-p或者-P選項生效。
# 只能設置一個變量 ENV <key> <value> # 容許一次設置多個變量 ENV <key>=<value> ...
ENV 指令用於設置環境變量,當容器運行時設置的環境變量會一直存在,能夠經過docker inspect
命令查看值,經過docker run --env <key>=<value>
命令設置改變環境變量
ADD 有兩種形式:
ADD <src>... <dest>
ADD ["<src>",... "<dest>"]
(包含空格路徑使用這種方式)ADD 從本機複製文件、目錄和遠程URLs,而且添加到鏡像文件系統的指定路徑中。
src 支持正則模糊匹配,使用GO語言的filepath.Match 規則。例如:
ADD hom* /mydir/ # adds all files starting with "hom" ADD hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
dest 路徑是絕對路徑,或者是WORKDIR
設置的相對路徑。
ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/ ADD test /absoluteDir/ # adds "test" to /absoluteDir/
ADD 服從如下規則:
ADD ../something /something
.COPY 有兩種形式:
COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
(包含空格路徑使用這種方式)COPY複製新文件或者目錄從 而且添加到容器指定路徑中 。用法同ADD,不一樣是不能指定src遠程文件 URLs和本機壓縮包不能解壓。
ENTRYPOINT 有兩種形式:
ENTRYPOINT ["executable", "param1", "param2"]
(exec 形式,首選)ENTRYPOINT command param1 param2
(shell 形式)ENTRYPOINT 容許配置容器啓動後執行的命令,而且不可被 docker run 提供的參數覆蓋,而CMD是能夠被覆蓋的。若是須要覆蓋,則可使用docker run --entrypoint
選項。
每一個 Dockerfile 中只能有一個ENTRYPOINT,當指定多個時,只有最後一個生效。
經過ENTRYPOINT使用 exec 形式 方式設置穩定的默認命令和選項,而使用CMD添加默認以外常常被改動的選項,例如:
FROM ubuntu ENTRYPOINT ["top", "-b"] CMD ["-c"]
運行容器,只顯示top一個進程
$ docker run -it --rm --name test top -H top - 08:25:00 up 7:27, 0 users, load average: 0.00, 0.01, 0.05 Threads: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 2056668 total, 1616832 used, 439836 free, 99352 buffers KiB Swap: 1441840 total, 0 used, 1441840 free. 1324440 cached Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 19744 2336 2080 R 0.0 0.1 0:00.04 top
進一步檢查運行的結果,經過docker exec
:
$ docker exec -it test ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 2.6 0.1 19752 2352 ? Ss+ 08:24 0:00 top -b -H root 7 0.0 0.1 15572 2164 ? R+ 08:25 0:00 ps aux
下面 Dockerfile 顯示使用ENTRYPOINT展現前臺運行 Apache 服務
FROM debian:stable RUN apt-get update && apt-get install -y --force-yes apache2 EXPOSE 80 443 VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"] ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
瞭解CMD和ENTRYPOINT怎樣相互影響:
CMD和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 | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
VOLUME ["/data"]
VOLUME指令建立一個具備指定名稱的掛載點,並將其標記爲從本機主機或其餘容器保存外部掛載的卷。值爲JSON格式,VOLUME ["/var/log/"]
,或者具備多個參數的字符串,例如:a plain string with multiple arguments
或VOLUME /var/log /var/db
,更多信息和用例參考Share Directories via Volumes
USER daemon
指定容器運行時的用戶名或UID,後續的RUN、CMD、ENTRYPOINT也會使用指定用戶。
WORKDIR 指令用來設置後續RUN
,CMD
,ENTRYPOINT
,COPY
和ADD
的指令在Dockerfile文件中的工做目錄,若是目錄不存在,則會建立。可使用多個WORKDIR指令,後續命令若是參數是相對路徑,則會基於以前命令指定的路徑。
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
最終路徑是/a/b/c
WORKDIR指令能夠在ENV設置變量以後調用環境變量:
ENV DIRPATH /path WORKDIR $DIRPATH/$DIRNAME RUN pwd
ONBUILD [INSTRUCTION]
配置當所建立的鏡像做爲其它新建立鏡像的基礎鏡像時,所執行的操做指令。
如,Dockerfile 使用以下的內容建立了鏡像 image-A:
[...] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
若是基於 image-A 建立新的鏡像時,新的 Dockerfile 中使用 FROM image-A 指定基礎鏡像時,會自動執行 ONBUILD 指令內容,等價於在後面添加了兩條指令。
# Automatically run the following ADD . /app/src RUN /usr/local/bin/python-build --dir /app/src