Dockerfile語法簡介

Dockerfile是由一系列命令和參數構成的腳本,一個Dockerfile裏面包含了構建整個image的完整命令。Docker經過docker build執行Dockerfile中的一系列命令自動構建image。html

# :表明註釋前端

1、 FROM

Syntax:docker

FROM  <image>[:<tag> | @<digest>] [AS <name>]
  • FROM指定一個基礎鏡像,且必須爲Dockerfile文件開篇的每一個非註釋行,至於image則能夠是任何合理存在的image鏡像shell

  • FROM能夠在一個Dockerfile中出現屢次,以便於建立混合的images。若是沒有指定tag,latest將會被指定爲要使用的基礎鏡像版本。後端

  • AS name,能夠給新的構建階段賦予名稱。該名稱可用於後續FROM 和 COPY --from=<name | index>說明能夠引用此階段中構建的鏡像數組


2、LABEL

爲鏡像生成元數據標籤信息
Syntax:緩存

LABEL <KEY>=<VALUE> \
    <KEY>="XXXX"

多個標籤寫成一行,避免在鏡像中額外增長layerruby


3、MAINTAINER

做者信息,寫在FROM後
Syntax:bash

MAINTAINER "auth <email>"


4、COPY

當複製一個目錄時,並不會複製目錄自己,而是會遞歸複製其下子目錄 至目標目錄下
Syntax:app

COPY data /data/

文件複製準則

  • <src>必須是build上下言文中的路徑,不能是其父目錄中的文件
  • 若是<src>是目錄,則其內部文件或子目錄會被遞歸複製,但<src>目錄自身不會被複制
  • 若是指定了多個<src>,或在<src>中使用了通配符,則<dest>必須是一個目錄,且必須以/結尾
  • 若是<dest>事先不存在,它將會被自動建立,這包括其父目錄路徑。


5、ADD

ADD指令相似於COPY指令,ADD支持使用TAR文件和URL路徑

Syntax:

ADD <src>...<dest>
ADD ["<src>",..."<dest>"]

操做準則

  • 若是<src>爲URL且<dest>不以/結尾,則<src>指定的文件將被下載並直接被建立爲<dest>;若是<dest>以/結尾,則文件名URL指定的文件將被直接下載並保存爲<dest>/<filename>
  • 若是<src>是一個本地文件系統上的壓縮格式的tar文件,它將被展開爲一個目錄,其行爲相似於"tar -x"命令;然而,經過URL獲取到的tar文件將不會自動展開。
  • 若是<src>有多個,或其間接或直接使用了通配符,則<dest>必須是一個以/結尾的目錄路徑;若是<dest>不以/結尾,則其被視做一個普通文件,<src>內容將被直接寫入到<dest>
  • 爲了讓鏡像儘可能小,最好不要使用 ADD 指令從遠程 URL 獲取包,而是使用 curl 和 wget。這樣你能夠在文件提取完以後刪掉再也不須要的文件來避免在鏡像中額外添加一層。
    示例:
額外操做:
ADD http://example.com/1.tar.gz /apps/
RUN tar xf /apps/1.tar.gz -C /apps/ && \
    /bin/sh -c /apps/***.sh
     
簡單操做:
RUN mkdir -p /iyunwen/server/ && \
        curl -SL http://example.com/1.tar.gz \
        | tar -xzC /iyunwen/server/ && \
        /bin/sh -c /apps/***.sh


6、WORKDIR

用於爲Dockerfile中全部RUN、CMD、ENTRYPOINT、COPY和ADD指令設定工做目錄
Syntax:

WORKDIR <dirpath>

在Dockerfile文件中,WORKDIR指令能夠出現屢次,其路徑也能夠爲相對路徑,不過,其是相對此前一個WORKDIR指令指定的路徑
另外,WORKDIR也可調用由ENV指定定義的變量

ex:

WORKDIR /var/log
    WORKDIR $STATEPATH


7、RUN

接受命令做爲參數並用於建立鏡像,在以前的commit層上造成新的層。
Syntax:

RUN \<command\>(如同執行shell命令 /bin/sh -c)
RUN ["executable","param1","param2"]
  • RUN 指令將在當前image中執行任意合法命令並提交執行結果。命令執行提交後,就會自動執行Dockerfile中的下一個指令。
  • 分層RUN指令和生成提交符合Docker的核心概念,其中提交很輕量,能夠從image將用於Dockerfile中的下一步。
  • exec形式使得能夠避免shell字符串變化,以及使用不包含指定的shell可執行文件的基本image來運行RUN命令。
  • 在shell形式中,可使用\(反斜槓)將單個RUN指令繼續到下一行。例如:
    RUN yum install -y \ openssl \ pcre-devel \ zlib
  • 第二種語法格式中的參數是一個JSON格式的數組,其中<executable>爲要運行的命令,後面的<paramN>爲傳遞給命令的選項或對數;然而,此種格式指定的命令不會以"/bin/sh -c"來發起,所以常見的shell操做如變量替換以及通配符(?,*等)替換將不會進行;不過,若是要運行的命令依賴於此shell特性的話,能夠將其替換爲相似下面的格式。
RUN ["/bin/bash","-c","<executable>","<param1>"]

RUN 指令的緩存在下一次構建期間不會自動失效。用於諸如:yum repolist 之類的指令的緩存將在下一次構建期間被重用。能夠經過--no-cache 參數來使RUN指令的緩存無效,例如: docker build --no-cache

管理命令
某些RUN 命令依賴於使用管道字符( | )將管道輸出到另外一個命令功能

RUN wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html

Docker使用 /bin/sh -c 解釋執行這些命令,解釋器只評估管道中最後一個操做的退出代碼以肯定成功。在上面的例子中,只要wc -l 命令成功,即便wget 命令失敗,該構建步驟也會成功並生成新的鏡像。

因爲管道中任何階段的錯誤而致使命令失敗,請預先 set -o pipefail && 確保意外錯誤可防止構建無心中成功。例如:
set -o pipefail : 表示在管道鏈接的命令序列中,只要有任何一個命令返回非0值,則整個管道返回非0值,即便最後一個命令返回0.

RUN set -o pipefail && wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html

注意:

並不是全部的shell都支持 -o pipefail 選項。在這種狀況下(例如 dash shell,這是基於Debian的映像上的默認shell),請考慮使用exec形式RUN來明確選擇一個支持該pipefail選項的shell。如:

RUN ["/bin/bash","-c","set -o pipefail && wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html"]


8、CMD

相似於RUN指令,CMD指令也可用於運行任何命令或應用程序,不過,兩者的運行時間點不一樣

  • RUN 指令運行於映像文件構建過程當中,而CMD指令運行於基於Dockerfile構建出的新鏡像文件啓動一個容器時。
  • CMD指令的首要目的在於爲啓動的容器指定默認要運行的程序,且其運行結束後,容器也將終止;不過,CMD指定的命令其能夠被docker run的命令行選項所覆蓋
  • 在Dockerfile中能夠存在多個CMD指令,但僅最後一個生效

Syntax:

CMD <command>   //支持命令展開,可是不支持傳遞信號 
CMD ["<executable>","<param1>","<param2>"]  //至關於容器的第一個命令,能夠接受信號
CMD ["param1","param2"]
前兩種語法格式的意義同RUN
第三種則用於爲ENTRYPOINT指令提供默認參數

CMD會在啓動容器的時候執行,build時不執行,而RUN只是在構建鏡像的時候執行,後續鏡像構建完成以後,啓動容器就與RUN無關了。這個命令就至關於在/etc/rc.d/rc.local中寫命令


9、ENTRYPOINT

相似CMD指令的功能,用於爲容器指定默認運行程序,從而使得容器像是一具單獨的可執行程序
與CMD不一樣的是,由ENTRYPOINT啓動的程序不會被docker run命令行指定的參數所覆蓋,並且,這些命令行參數會被看成參數傳遞給ENTRYPOINT指定的程序。不過,docker run 命令的--entrypoint 選項的參數可覆蓋ENTRYPOINT指令指定的程序

Syntax:

ENTRYPOINT <command>    //這種方式能接受shell命令行展開
ENTRYPOINT ["<executable>","param1"]  //展開不了,但能接收到信號

docker run命令傳入的命令參數會覆蓋CMD指令的內容而且附加到ENTRYPOINT命令最後作爲其參數使用。Dockerfile文件中也能夠存在多個ENTRYPOINT指令,但僅有最後一個會生效


10、EXPOSE

用來指定端口,使容器內的應用能夠經過端口和外界交互。
Syntax:

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

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

EXPOSE 80/tcp


11、ENV

ENV指令能夠用於docker容器設置環境變量
Syntax:

ENV <key> <value>
ENV <key>=<value> ...

指定一個環境變量,會被後續RUN指令使用,並在容器運行時保留。
ENV設置的環境變量,可使用 docker inspect 命令來查看。同時還可使用 docker run --env <key>=<value>來修改環境變量


12、USER

用於指定運行image時的或運行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序時的用戶名或UID
默認狀況下,container的運行身份爲root用戶
Syntax:

USER <UID>|<UserName>

須要注意的是,<UID>能夠爲任意數字,但實踐中其必須爲/etc/passwd中某用戶的有效UID,不然,docker run命令將運行失敗


十3、ONBUILD

用於在Dockerfile中定義一個觸發器
Dockerfile用於build映像文件,此映像文件亦可做爲base image被另外一個Dockerfile用做FROM指令的參數,並以之構建新的映像文件
在後的這個Dockerfile中的FROM指令在build過程當中被執行時,將會「觸發」建立其base image的Dockerfile文件中的ONBUILD指令定義的觸發器

Syntax:

ONBUILD <INSTRUCTION>

注意:
儘管任何指令均可註冊成爲觸發器指令,但ONBUILD不能自我嵌套,且不會觸發FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile構建的鏡像應該使用特殊的標籤,例如ruby:2.0-onbuild
在ONBUILD指令中使用ADD或COPY指令應該格外當心,由於新構建過程和上下文在缺乏指定的源文件時會失敗。


十4、HEALTHCHECK

Docker 1.12版本後引入的判斷容器狀態是否正常

Syntax:

HEALTHCHECK [OPTION] CMD <command>  //設置檢查容器健康情況的命令 
HEALTHCHECK NONE   //若是基礎鏡像有健康檢查指令,使用這行可屏蔽掉其健康檢查指令

在沒HEALTHCHECK指令前,Docker只能經過容器內主進程是否退出來判斷容器是否狀態異常。不少狀況下這沒問題,可是若是程序進入死鎖狀態,或者死循環狀態,應用進程並不退出,可是該容器已經沒法提供服務了。雖而後端的程序能夠經過前端的檢測工具來檢查狀態信息。可是最前端的服務就須要自己的檢測機制加上監控,就能夠作到出現問題解決問題。

當在一個鏡像指定了 HEALTHCHECK 指令後,用其啓動容器,初始狀態會爲 starting,在 HEALTHCHECK 指令檢查成功後變爲 healthy,若是連續必定次數失敗,則會變爲 unhealthy。

HEALTHCHECK支持下列選項:

  • --interval= <間隔> : 兩次健康檢查間隔,默認30秒
  • --timeout= <時長> : 健康檢查命令運行超時時間,若是超過這個時間,本次健康檢查就被視爲失敗,默認爲30秒
  • --retries= <次數> :當連續失敗指定次數後,則將容器狀態視爲unhealthy,默認3次。

和CMD、ENTRYPOINT同樣,HEALTHCHECK只能夠出現一次,若是寫了多個,只有最後一個生效。CMD 後面的命令也分爲shellexec格式。命令的返回值決定了該次檢查的成功與否: 0表示成功;1表示失敗;2保留。

ex:

HEALTHCHECK --interval=5s --timeout=3s \
  CMD curl -fs http://localhost/ || exit 1
相關文章
相關標籤/搜索