Dockerfile 的使用

Dockerfile 的使用

Docker build命令和鏡像構建過程

docker build命令使用的時候其參數有3種類型來表示構建context的3種來源:PATH, -URL更多>>

這里的構建context是指傳入docker build命令的所有文件。
一般情況下,將本地主機的一個包含Dockerfile的目錄中的所有內容作為context。context通過docker build命令傳入到Docker daemon后,便開始按照Dockerfile中的內容構建鏡像。

除了FROM指令,其它每一條指令都會在上一條指令所生成的鏡像的基礎上執行,執行完后會生成一個新的鏡像層,新的鏡像層覆蓋在原來的鏡像之上從而形成了新鏡像。Dockerfile所生成的最終鏡像就是在基礎鏡像上面疊加一層層的鏡像層組建的

為了提高鏡像構建的速度,Docker daemon會緩存構建過程中的中間鏡像。當從一個已經在緩存中的基礎鏡像開始構建新鏡像時,會像Dockerfile中的下一條指令和基礎鏡像的所有子鏡像做比較,如果有一個子鏡像是由相同命令生成的,則命中緩存,直接使用該鏡像,而不用再生成一個新的鏡像。

但是COPYADD命令與其它命令稍有不同,其他指令只對比生成鏡像的指令字符串是否相同;COPYADD還要對比容器中的文件內容和所添加的文件內容是否相同。此外,鏡像構建過程中,一旦緩存失效,則后續的指令都將生成新的鏡像,而不再使用緩存。

Dockerfile指令

  • FROM

格式:

FROM <image>

FROM <image>:<tag>

FROM指令為后面的指令提供基礎鏡像,因些一個有效的Dockerfile必須以FROM作為第一條非注釋指令。

  • ENV

格式:

ENV <key> <value>

ENV <key>=<value>

ENV用于聲名明境變量。并且在Dockerfile中ENV指令聲明環境可以被后面的特定指令(ENV,ADD,COPY,WORKDIR,EXPOSE,VOLUME,USER)解釋使用。

使用格式:

$variable_name

${variable_name}
  • COPY

格式:

COPY <src> <dest>

<src>所指定的源可以有多個,但必須在context中,即必須是context根目錄的相對路徑。不能使用形如COPY ../something /something這樣的指令。此外,<src>可以使用通配符指向所有匹配通配符的文件或目錄,如,COPY hom* /mydir/

<dest>可以是文件或目錄,但必須是目標鏡像中的絕對路徑或者相對于WORKDIR的相對路徑。

  • ADD

格式:

ADD <src> <dest>

ADDCOPY在功能上很相似,但ADD還支持其他功能。<src>可以是一個指向一個網絡文件的URL,此時若<dest>指向一個目錄,則URL必須是完全路徑,這樣可以獲得該網絡文件名filename,該文件會被復制添加到<dest>/<filename>。例如,ADD http://example.com/foobar /會創建文件/foobar。

一般推薦使用COPY,因為COPY只支持本地文件,相比ADD而言,它更透明。

  • RUN

格式:

RUN <command>  // shell格式

RUN ["executable", "param1", "param2"] // exec格式,推薦格式

RUN指令會在前一條命令創建出的鏡像的基礎上創建一個容器,并在容器中運行命令,在命令結束運行后提交容器為新鏡像。

當使用shell格式時,命令通過/bin/sh -c運行;
當使用exec格式時,命令是直接運行的,容器不調用shell程序,即容器中沒有shell程序。exec格式中的參數會當成JSON數組被Docker解析,故必須使用雙引號而不能使用單引號。因為exec格式不會在shell中執行,所以環境變量的參數不會被替換。

  • CMD

格式:

CMD <command> // shell格式
CMD ["executable", "param1", "param2"] // exec格式,推薦格式
CMD ["param1", "param2"] // 為ENTRYPOINT指令提供參數

CMD提供運行的默認值,默認值可以是一些參數,或指令。一個Dockerfile中只有最后一條CMD指令有效。而且CMD指令需要要ENTRYPOINT指令配合使用。

RUN指令不周的是:

RUN指令在構建鏡像時執行命令,并生成的鏡像;

CMD指令在構建鏡像時并不執行任何命令,而是在容器啟動時默認將CMD指令作為第一條執行的命令。如果用戶在命令行界面運行docker run命令時指定了命令參數,則會覆蓋CMD指令中的命令。

  • ENTRYPOINT

格式:

ENTRYPOINT <command> // shell格式

ENTRYPOINT ["executable", "param1", "param2"] // exec格式,推薦格式

ENTRYPOINT指令和CMD指令類似,都可以讓容器在每次啟動時執行相同的命令。但它們之間又有不同。一個Dockerfile中只有最后一條ENTRYPOINT指令有效。

當使用sheel格式時,ENTRYPOINT指令會忽略任何CMD指令和docker run命令的參數,并且運行在bin/sh -c中。這意味著ENTRYPOINT指令進程為bin/sh -c的子進程,進程在容器中的PID將不是1,且不能接受Unix信號。即當使用docker stop <container>命令時,命令進程接受不到SIGTERM信號。

我們推薦使用exec格式,使用此格式時,docker run傳入的命令參數會覆蓋CMD指令的內容,并且添加到ENTRYPOINT指令的參數中。

ENTRYPOINT的使用中可以看出,CMD可以是參數,也可以是指令,而ENTRYPOINT只能是命令;另外,docker run提供的運行命令參數可以覆蓋CMD,但是不能覆蓋ENTRYPOINT

Dockerfile 使用心得

  • 使用標簽

給鏡像打標簽,易讀的鏡像標簽可以幫助了解鏡像的功能,如:

docker build -t "mydockerimage:1.0" .
  • 謹慎選擇基礎鏡像

busybox < debian < centos < ubuntu

  • 充分利用緩存

為了有效地利用緩存,需要保證指令的連續性,盡量將所有Dockerfile文件中相同的部分都放在前面,而將不同的部分放在后面。

  • CMD和ENTRYPOINT

CMDENTRYPOINT指令指定了容器運行的命令,推薦二者結合使用。使用exec格式的ENTRYPOINT指令設置固定的默認命令和參數,然后使用CMD指令設置可變的參數。

  • 不要在Dockerfile中做端口映射

Docker的兩個核心概念是可重復性可移植性,鏡像應該可以在任何主機上運行多次。使用Dockerfile的EXPOSE指令,雖然可以將容器端口映射到主機端口上,但會破壞Docker的可移植性,且這樣的鏡像在一臺主機上只能啟動一個容器。所以端口映射就在docker run命令中用-p參數指定。

# 不要在Dockerfile中做如下映射
EXPOSE 80:8080

# 僅僅暴露80端口,需要另做映射
EXPOSE 80
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Docker — 云時代的程序分發方式 要說最近一年云計算業界有什么大事件?Google Compute Engi...
    ahohoho閱讀 15,627評論 15 147
  • 轉載自 http://blog.opskumu.com/docker.html 一、Docker 簡介 Docke...
    極客圈閱讀 10,543評論 0 120
  • docker基本概念 1. Image Definition 鏡像 Image 就是一堆只讀層 read-only...
    慢清塵閱讀 8,816評論 1 21
  • 謝公天眷顧,貌質自峨巍。 才斗千層厚,文情百丈菲。 遂邀巖上月,又瞰霧中輝。 喜作逍遙客,云山帶暮歸。
    作家魏潘閱讀 468評論 8 13
  • 我的小喵你醒了嗎 昨晚下了轟隆隆的雷雨 睡不著的時候 我想翻越所有的孤獨去擁抱你 可你在我懷里卻依舊怕 我想送你世...
    杜小螢閱讀 319評論 0 1