Dockerfile命令詳解

什么是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ù)階段的FROMCOPY --from=<name|index>使用阀捅。
    • tag和digest是可選的胀瞪,如果不提供則使用latest。
  • 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ù)翠储,那么CMDENTRYPOINT指令都應(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>
    

    LABELMAINTAINER更靈活,推薦使用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指令有兩種格式:

    1. ENV <key> <value>:把第一個空格之后的所有值都當(dāng)做<key>的值彩掐,無法在一行內(nèi)設(shè)定多個環(huán)境變量。
    2. 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指令

    CMDENTRYPOINT至少得使用一個。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指令指定用戶涕俗。受影響的指令有:RUNCMD神帅、ENTRYPOINT再姑。

    USER <user>[:<group>] or
    USER <UID>[:<GID>]
    

    注意:當(dāng)用戶沒有主要組時,鏡像(或下一條指令)將與該root組一起運行找御。

  • WORKDIR
    為接下來的Dockerfile指令指定當(dāng)前工作目錄元镀,可多次使用,如果使用的是相對路徑霎桅,則相對的是上一個工作目錄栖疑,類似shell中的cd命令。

    WORKDIR /path/to/workdir
    

    受影響的指令有:RUN滔驶、CMD遇革、ENTRYPOINTCOPYADD
    可以在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
    

    您可以使用ARGENV指令指定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_proxyHTTPS_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:

    1. --interval=DURATION(檢測間隔,默認值:30s)
    2. --timeout=DURATION(命令超時時間缝其,默認值:30s)
    3. --start-period=DURATION(初始化后開始檢查時間挎塌,默認值:0s)
    4. --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"]
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末询件,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子唆樊,更是在濱河造成了極大的恐慌宛琅,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逗旁,死亡現(xiàn)場離奇詭異嘿辟,居然都是意外死亡舆瘪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門红伦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來英古,“玉大人,你說我怎么就攤上這事昙读≌俚鳎” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵蛮浑,是天一觀的道長唠叛。 經(jīng)常有香客問我,道長沮稚,這世上最難降的妖魔是什么艺沼? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮壮虫,結(jié)果婚禮上澳厢,老公的妹妹穿的比我還像新娘。我一直安慰自己囚似,他們只是感情好剩拢,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著饶唤,像睡著了一般徐伐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上募狂,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天办素,我揣著相機與錄音,去河邊找鬼祸穷。 笑死性穿,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的雷滚。 我是一名探鬼主播需曾,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼祈远!你這毒婦竟也來了呆万?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤车份,失蹤者是張志新(化名)和其女友劉穎谋减,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扫沼,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡出爹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年庄吼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片以政。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡霸褒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盈蛮,到底是詐尸還是另有隱情废菱,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布抖誉,位于F島的核電站殊轴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏袒炉。R本人自食惡果不足惜旁理,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望我磁。 院中可真熱鬧孽文,春花似錦、人聲如沸夺艰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽郁副。三九已至减牺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間存谎,已是汗流浹背拔疚。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留既荚,地道東北人稚失。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像恰聘,于是被迫代替她去往敵國和親句各。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354