Docker Dockerfile指令

Docker 能夠經過 Dockerfile 的內容來自動構建鏡像。Dockerfile 是一個包含建立鏡像全部命令的文本文件,經過docker build命令能夠根據 Dockerfile 的內容構建鏡像,在介紹如何構建以前先介紹下 Dockerfile 的基本語法結構。python

Dockerfile 有如下指令選項:
FROM、LABEL、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD

FROM

用法:linux

FROM <image>

或者golang

FROM <image>:<tag>

或者docker

FROM <image>@<digest>

FROM指令設置基本鏡像用於後續指令;若是本地沒有指定的鏡像,則會自動從 Docker 的公共庫 pull 鏡像下來。shell

  • 鏡像必須是Dockerfile文件中第一條非註釋指令
  • FROM 指令能同一個Dockerfile文件中出現屢次,爲了建立多個鏡像
  • tag 和 digest 值是可選的,若是缺省,構建器默認爲latest,當tag不匹配時,構建器返回錯誤

RUN

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 指令有三種形式:

  • 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

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 (已廢棄)

MAINTAINER <name>

MAINTAINER用戶設置鏡像的做者。LABEL指令能夠更靈活的代替,例如:

LABEL maintainer "SvenDowideit@home.org.au"

EXPOSE

EXPOSE <port> [<port>...]

告訴 Docker 服務端容器對外映射的本地端口,須要在 docker run 的時候使用-p或者-P選項生效。

ENV

# 只能設置一個變量
ENV <key> <value>

# 容許一次設置多個變量
ENV <key>=<value> ...

ENV 指令用於設置環境變量,當容器運行時設置的環境變量會一直存在,能夠經過docker inspect命令查看值,經過docker run --env <key>=<value>命令設置改變環境變量

ADD

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 服從如下規則:

  • src 路徑必須在Dockerfile文件路徑下,不能使用ADD ../something /something.
  • 若是src是URL,而且dest不以尾部斜線結尾,則從URL下載文件並複製到dest
  • 若是src是目錄,則複製目錄下所有內容,而目錄自己則不會被複制
  • 若是src是在本機的經常使用壓縮格式文件,將會解壓成目錄,若是是url 遠端的,則不會解壓
  • 若是src有多個文件,dest必須是目錄,而且以/結尾
  • 若是dest不存在,則會建立一個路徑

COPY

COPY 有兩種形式:

  • COPY <src>... <dest>
  • COPY ["<src>",... "<dest>"](包含空格路徑使用這種方式)

COPY複製新文件或者目錄從 而且添加到容器指定路徑中 。用法同ADD,不一樣是不能指定src遠程文件 URLs和本機壓縮包不能解壓。

ENTRYPOINT

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指令都定義了運行容器時執行的命令。
如下是描述他們合做的規則:

  1. Dockerfile 文件至少有一個CMD或者ENTRYPOINT命令
  2. 使用容器執行時,應定義ENTRYPOINT
  3. CMD 指令能夠定義默認的參數做爲ENTRYPOINT命令
  4. CMD 指令能夠被容器運行時指定的命令覆蓋
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

VOLUME ["/data"]

VOLUME指令建立一個具備指定名稱的掛載點,並將其標記爲從本機主機或其餘容器保存外部掛載的卷。值爲JSON格式,VOLUME ["/var/log/"],或者具備多個參數的字符串,例如:a plain string with multiple argumentsVOLUME /var/log /var/db,更多信息和用例參考Share Directories via Volumes

USER

USER daemon

指定容器運行時的用戶名或UID,後續的RUN、CMD、ENTRYPOINT也會使用指定用戶。

WORKDIR

WORKDIR 指令用來設置後續RUN,CMD,ENTRYPOINT,COPYADD的指令在Dockerfile文件中的工做目錄,若是目錄不存在,則會建立。可使用多個WORKDIR指令,後續命令若是參數是相對路徑,則會基於以前命令指定的路徑。

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

最終路徑是/a/b/c

WORKDIR指令能夠在ENV設置變量以後調用環境變量:

ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd

ONBUILD

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
相關文章
相關標籤/搜索