Dockerfile書寫規(guī)則

Dockerfile書寫規(guī)則

官方建議指令越少越好,每一個(gè)指令都會(huì)創(chuàng)建一層,極占空間。

FROM

指定目前需要構(gòu)建鏡像的基礎(chǔ)鏡像

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]

# --platform 可選 用于指定構(gòu)建的平臺(tái),默認(rèn)不填為本機(jī)平臺(tái)
# image 必填 鏡像名 所有鏡像默認(rèn)繼承scratch鏡像
# tag 可選 鏡像標(biāo)簽,默認(rèn)為latest
# digest 可選 摘要,默認(rèn)為latest
# AS 可選 別名,用于后續(xù)的鏡像階段構(gòu)建
# FROM --platform=linux/amd64 mongo:4.3 AS db

RUN

兩種寫法,bash-like或者json-like

  • RUN <command> shell-like寫法,直接執(zhí)行命令,在Linux中默認(rèn)執(zhí)行 /bin/sh -c,Windows中默認(rèn)執(zhí)行 cmd /S /C
# 使用反斜杠換行書寫
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
  • RUN ["executable", "param1", "param2"]
# 參數(shù)是json-like書寫格式,需要使用雙引號(hào)
# json-like寫法不支持“$HELLO”的環(huán)境變量
RUN ["/bin/bash", "-c", "echo hello"]

CMD

與RUN命令區(qū)別在于,RUN命令直接執(zhí)行并提交結(jié)果,CMD只是將命令存下來,等容器啟動(dòng)時(shí)才執(zhí)行;與ENTRYPOINGT命令配合使用效果更佳

  • CMD ["executable","param1","param2"] json-like

  • CMD ["param1","param2"] 作為ENTERYPOINT指令的默認(rèn)參數(shù)

  • CMD command param1 param2 shell-like

demo區(qū)分RUN和CMD

FROM alpine

RUN echo "hahaha run test"

CMD ["echo","hahahaha CMD"]
[root@seeter hu5ky]# docker build -t test:testruncommond .
Sending build context to Docker daemon   2.56kB
Step 1/3 : FROM alpine
 ---> cc0abc535e36
Step 2/3 : RUN echo "hahaha run test"
 ---> Running in b3d0cb324936
hahaha run test    ----------> RUN命令直接執(zhí)行
Removing intermediate container b3d0cb324936
 ---> e920fa254b3e
Step 3/3 : CMD ["echo","hahahaha CMD"]
 ---> Running in bd23af78c1e0     -----------> 不執(zhí)行
Removing intermediate container bd23af78c1e0
 ---> 1ec19a656013
Successfully built 1ec19a656013
Successfully tagged test:testruncommond

---------------------------
[root@seeter hu5ky]# docker run test:testruncommond 
hahahaha CMD ---------> docker run后才會(huì)執(zhí)行

LABEL

用來設(shè)定docker鏡像的metadata(鏡像的描述數(shù)據(jù)類似位置,大小,作者等),以鍵值對(duì)的形式存在

LABEL <key>=<value> <key>=<value> <key>=<value> ...
------------
# 多標(biāo)簽寫法
LABEL "auth"="hu5ky" 
LABEL "time"="2020/04/27"

# 單標(biāo)簽單行寫法
LABEL "auth"="hu5ky" "time"="2020/04/27"

# 單標(biāo)簽多行寫法(個(gè)人推薦)
LABEL "auth"="hu5ky" \
      "time"="2020/04/27"

demo

[root@firevision-aibuilding-test zc]# docker image inspect --format='{{.Config.Labels}}' test:testruncommond
map[auth:hu5ky time:2020/04/27]

MAINTAINER

MAINTAINER <name> <email> 

鏡像創(chuàng)建者 官方不推薦使用,可以使用

LABEL maintainer="SvenDowideit@home.org.au" eg. 

EXPOSE

用于在運(yùn)行時(shí)暴露容器端口并指定協(xié)議,未指定協(xié)議則默認(rèn)為TCP

EXPOSE <port> [<port>/<protocol>...]

EXPOSE 80/tcp
EXPOSE 80/udp

EXPOSE可以配合-P/-p命令使用:

  • -P 當(dāng)使用 -P 標(biāo)記時(shí),Docker 會(huì)隨機(jī)映射一個(gè) 49000~49900 的端口到內(nèi)部容器開放的網(wǎng)絡(luò)端口。
  • -p -p(小寫)則可以指定要映射的IP和端口,但是在一個(gè)指定端口上只可以綁定一個(gè)容器。支持的格式有hostPort:containerPort ip:hostPort:containerPort ip::containerPort。-p命令會(huì)直接忽略 EXPOSE 中的端口.

ENV

k-v鍵值對(duì),用于設(shè)定環(huán)境變量

  • ENV <key> <value> # 一次設(shè)置一個(gè)
  • ENV <key>=<value> ... # 一次設(shè)置多個(gè)

docker run --env時(shí)可以對(duì)Fockerfile的ENV參數(shù)進(jìn)行修改

ADD

將宿主機(jī)的文件或遠(yuǎn)程文件添加到容器內(nèi)部

  • ADD [--chown=<user>:<group>] <src>... <dest>

  • ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] 如果文件路徑包含空格,使用這種方式。

demo

# 支持通配符寫法
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/

# --chown 可選 指定用戶與組對(duì)應(yīng)關(guān)系
# src 必填 宿主機(jī)文件或者url 如果為URL需要權(quán)限驗(yàn)證,嘖需要第三方工具下載,ADD命令不支持驗(yàn)權(quán)
# dest 必填 docker內(nèi)部路徑

ADD命令遵循以下規(guī)則

  • src中的路徑不可以是相對(duì)路徑,錯(cuò)誤寫法:ADD ../something /something。因?yàn)镈ockerfile第一步就是將當(dāng)前上下文以及子路徑發(fā)送到docker daemon中。../的寫法不被支持。

  • 如果src是一個(gè)URL,且dest最后不以斜杠/結(jié)尾,則URL中文件被下載并拷貝到dest中。

  • 如果src是一個(gè)URL,則docker自動(dòng)將url最后的名稱作為目標(biāo)路徑的文件名。

    # 正確用法
    ADD http://example.com/foobar / # 最后會(huì)出現(xiàn)/foobar文件
    # 錯(cuò)誤寫法
    ADD http://example.com / # 無效
    
  • 如果src 是一個(gè)目錄,則整個(gè)目錄都會(huì)被拷貝,包括文件系統(tǒng)的metadata,但是文件夾不會(huì)被拷貝,只會(huì)拷貝其中的內(nèi)容。

  • 如果src是一個(gè)壓縮包,則會(huì)被解壓到dest

COPY

ADD,只是src不能為URL

  • COPY [--chown=<user>:<group>] <src>... <dest>

  • COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

ENTRYPOINT

  • ENTRYPOINT ["executable", "param1", "param2"] json-like

  • ENTRYPOINT command param1 param2 bash-like

CMD比較

  • docker run指定command時(shí),CMD指令會(huì)被覆蓋,而ENTRYPOINT不會(huì)

demo

FROM ubuntu
CMD echo hahahahahahCMD
ENTRYPOINT ["echo", "hahahahha entrypoint"]
ENTRYPOINT echo hahahhhahahahENTRYPOINT
# ENTRYPOINT 不會(huì)被覆蓋
[root@seeter hu5ky]# docker run test:test echo hahahahecho
hahahhhahahahENTRYPOINT

FROM ubuntu
CMD echo hahahahahahCMD
# CMD被command替換
[root@seeter hu5ky]# docker run test:test echo hahahahecho
hahahahecho
  • CMDENTRYPOINT同時(shí)使用時(shí),CMD將作為ENTRYPOINT的參數(shù)。

demo

FROM ubuntu
CMD echo hahahahahahCMD
ENTRYPOINT ["echo", "hahahahha entrypoint"]
# CMD被視為ENTRYPOINT參數(shù)
[root@seeter hu5ky]# docker run test:test
hahahaha entrypoint echo hahahaha CMD
  • 多個(gè)ENTRYPOINT同時(shí)使用時(shí),最后一個(gè)ENTRYPOINT生效。

demo

FROM ubuntu
CMD echo hahahahahahCMD
ENTRYPOINT ["echo", "hahahahha entrypoint"]
ENTRYPOINT echo hahahhhahahahENTRYPOINT
[root@seeter hu5ky]# docker run test:test
hahahhhahahahENTRYPOINT

VOLUME

  • VOLUME ["/data"]

  • VOLUME /data

作用僅僅是創(chuàng)建一個(gè)匿名掛載點(diǎn),指定host存儲(chǔ)時(shí),需使用docker run -v

USER(待補(bǔ)充)

  • USER <user>[:<group>]

  • USER <UID>[:<GID>]

WORKDIR

WORKDIR后的所有命令指定運(yùn)行目錄

  • WORKDIR /path/to/workdir

demo

# 如果使用多次`WORKDIR`指令,且第一個(gè)是絕對(duì)路徑,后面的是相對(duì)路徑,則后續(xù)的所有路徑就將追加在前一個(gè)路徑中
FROM ubuntu
WORKDIR /app
WORKDIR hu5ky
RUN pwd
CMD echo hahahahahahCMD
VOLUME /home/hu5ky/volume/ /app/volume/
[root@seeter hu5ky]# docker build -t test:test .
Sending build context to Docker daemon  3.072kB
Step 1/6 : FROM ubuntu
 ---> 1d622ef86b13
Step 2/6 : WORKDIR /app
 ---> Running in 252cabc124c2
Removing intermediate container 252cabc124c2
 ---> 0577acce038d
Step 3/6 : WORKDIR hu5ky
 ---> Running in 83a45ee392c2
Removing intermediate container 83a45ee392c2
 ---> 8e3a8ccfd5b4
Step 4/6 : RUN pwd
 ---> Running in c66ebc01af08
/app/hu5ky ----------->完整路徑
···

demo

# 可以結(jié)合環(huán)境變量使用
FROM ubuntu
ENV DIRPATH /app
WORKDIR $DIRPATH
WORKDIR hu5ky/$PPP
RUN pwd
[root@seeter hu5ky]# docker build -t test:test .
Sending build context to Docker daemon  3.072kB
Step 1/5 : FROM ubuntu
 ---> 1d622ef86b13
Step 2/5 : ENV DIRPATH /app
 ---> Using cache
 ---> 072a81455e5d
Step 3/5 : WORKDIR $DIRPATH
 ---> Running in 1c40421a9bb3
Removing intermediate container 1c40421a9bb3
 ---> 881bb05f37ce
Step 4/5 : WORKDIR hu5ky/$PPP
 ---> Running in 055cbeedebda
Removing intermediate container 055cbeedebda
 ---> 36b3343fa7cc
Step 5/5 : RUN pwd
 ---> Running in f4ee0bbb3182
/app/hu5ky ---------> 輸出路徑
Removing intermediate container f4ee0bbb3182
 ---> 8a6c3f753250
Successfully built 8a6c3f753250
Successfully tagged test:test

ARG

如果在FROM前使用了ARG,這個(gè)ARG只能在FROM中使用,在FROM之后的指令中全都無效

  • ARG <name>[=<default value>] 缺省值會(huì)被--build-arg <varname>=<value>替換

用戶可以通過docker build中的--build-arg <varname>=<value>參數(shù)來指定,如果Dockerfile中沒有指定ARG參數(shù),在build時(shí)會(huì)報(bào)出warning
demo

FROM ubuntu
ARG user
RUN echo $user
[root@firevision-kgm-test zhangc]# docker build --build-arg user=what_user .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM ubuntu
 ---> 1d622ef86b13
Step 2/3 : ARG user
 ---> Running in 46f865af728e
Removing intermediate container 46f865af728e
 ---> 3742534d7867
Step 3/3 : RUN echo $user
 ---> Running in 5535d80b3b89
what_user. ------> 輸出
Removing intermediate container 5535d80b3b89
 ---> 856eec9724e5
Successfully built 856eec9724e5

同時(shí)使用ARGENV指令,以ENV的參數(shù)為準(zhǔn),一般來說ENV的優(yōu)先級(jí)高于ARG
demo

FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER v1.0.0
RUN echo $CONT_IMG_VER
[root@seeter hu5ky]# docker build --build-arg CONT_IMG_VER=v2.0.1 .
Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM ubuntu
 ---> 1d622ef86b13
Step 2/4 : ARG CONT_IMG_VER
 ---> Using cache
 ---> 993483f26804
Step 3/4 : ENV CONT_IMG_VER v1.0.0
 ---> Running in 2535a58ab1d4
Removing intermediate container 2535a58ab1d4
 ---> bc3012e82989
Step 4/4 : RUN echo $CONT_IMG_VER
 ---> Running in c55abb96daf7
v1.0.0. ---------> env指令的參數(shù)
Removing intermediate container c55abb96daf7
 ---> 114fc834f42d
Successfully built 114fc834f42d

結(jié)合ENVARG使用demo

FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}
RUN echo $CONT_IMG_VER
[root@seeter hu5ky]# docker build .
Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM ubuntu
 ---> 1d622ef86b13
Step 2/4 : ARG CONT_IMG_VER
 ---> Running in 2ccf8e734837
Removing intermediate container 2ccf8e734837
 ---> af95bb2aeb4b
Step 3/4 : ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}
 ---> Running in 3bf09240355e
Removing intermediate container 3bf09240355e
 ---> d845d51f801f
Step 4/4 : RUN echo $CONT_IMG_VER
 ---> Running in 8b34d0bd089b
v1.0.0
Removing intermediate container 8b34d0bd089b
 ---> e00f86d7c62a
Successfully built e00f86d7c62a

ARG指令有一組預(yù)定義的參數(shù),不需要在Dockerfile中指定

HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy

直接在--build-arg <varname>=<value>中指定即可

ONBUILD(待補(bǔ)充)

ONBUILD <INSTRUCTION>

STOPSIGNAL(待補(bǔ)充)

  • STOPSIGNAL signal

HEALTHCHECK

用來告訴Docker怎么去檢查容器的運(yùn)行情況,甚至可以檢測(cè)出一個(gè)運(yùn)行的容器中存在的死循環(huán)和無法創(chuàng)建新鏈接的情況

  • HEALTHCHECK [OPTIONS] CMD command

  • HEALTHCHECK NONE

當(dāng)指定了運(yùn)行狀況檢查的容器時(shí),除了其正常狀態(tài)外,它還具有運(yùn)行狀況。此狀態(tài)最初為starting。只要運(yùn)行狀況檢查通過,它將變?yōu)閔ealthy(以前處于任何狀態(tài))。在一定數(shù)量的連續(xù)失敗之后,它變?yōu)閡nhealthy.

  • --interval=DURATION (默認(rèn) 30s)

  • --timeout=DURATION (默認(rèn) 30s)

  • --start-period=DURATION (默認(rèn) 0s)

  • --retries=N (默認(rèn) 3)

運(yùn)行狀況檢查將首先在容器啟動(dòng)后的間隔秒數(shù)--interval內(nèi)運(yùn)行,然后在之前每次檢查完成后的間隔秒數(shù)內(nèi)運(yùn)行。

如果單次檢查花費(fèi)的時(shí)間超過超時(shí)--timeout秒數(shù),則認(rèn)為檢查失敗。

連續(xù)多次重試--retries失敗后,才可以將某一容器的狀態(tài)判斷為unhealthy。

開始時(shí)間段--start-period為需要時(shí)間進(jìn)行 bootstrap 的容器提供了初始化時(shí)間。在此期間內(nèi)的探針故障將不計(jì)入最大重試次數(shù)--retries。但是,如果運(yùn)行狀況檢查在啟動(dòng)期間成功,則認(rèn)為該容器已啟動(dòng),并且所有連續(xù)失敗將計(jì)入最大重試次數(shù)--retries。

Dockerfile文件中只允許出現(xiàn)一次HEALTHCHECK,多個(gè)該指令最后一個(gè)生效。

HEALTHCHECK后面可以跟CMD指令,例如:HEALTHCHECK CMD /bin/check-running,此CMD命令和Dockerfile中的一樣,shell-like和json-like。

  • 0: success - 可用
  • 1: unhealthy - 有問題
  • 2: reserved - 保留字段,官方不讓使用這個(gè)

每5m檢查一次,3s超時(shí)則為失敗
demo

HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

SHELL(待補(bǔ)充)

  • SHELL ["executable", "parameters"] 必須為json-like
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容