Docker初體驗,關于Dockerfile那點事

一、Dockerfile的格式

Dockerfile的格式如下:

# Comment

以“#”開頭的行為注釋行??缧凶⑨屢脖仨毤印?”,Dockerfile不支持連續(xù)字符“\”。命令解析指令也是以“#”開頭,命令解析器是一個可選項,位于Dockerfile的首行,只允許出現(xiàn)一次,第二次出現(xiàn)則被認為是注釋,在解析器中換行符同樣是不被支持的,但是其中的非斷行空格是允許的。

#directive=value
# directive =value
#   directive= value
# directive = value 

# escap

Escape在dockerfile中被用作轉義字符和換行符,如果不特別指定,系統(tǒng)默認的轉義字符為:\ (反斜杠)。轉義不能在RUN命令中執(zhí)行,除非位于行末進行格式換行。作為換行符時,escape允許Dockerfile指令跨行執(zhí)行。反引號在Windows下非常有用(舉例可以參閱官方文檔

# escape=\ (反斜杠)
或
# escape=` (反引號)

INSTRUCTION arguments

INSTRUCTION一般被稱為指令或者命令,對大小寫不敏感,為了與其他參數區(qū)別開,習慣大寫。

.dockerfileignore file

使用Dockerfile構建鏡像時最好是將Dockerfile放置在一個新建的空目錄下。然后將構建鏡像所需要的文件添加到該目錄中。為了提高構建鏡像的效率,你可以在目錄下新建一個.dockerignore文件來指定要忽略的文件和目錄。.dockerignore文件的排除模式語法和 Git的.gitignore文件相似。

二、相關指令詳解

FROM

每個Dockerfile必須以FROM指令開頭,F(xiàn)ROM指明了當前鏡像創(chuàng)建的基鏡像,也就是說每個鏡像必須基于一個已存在的鏡像進行創(chuàng)建。FROM指令后直接跟基鏡像的名稱或者鏡像名稱加標簽。鏡像的名稱和標簽可以去Docker Hub或者使用命令docker search keyword 進行搜索。用法如下:

FROM <image>

FROM <image>[:<tag>] 

ARG

ARG指令定義了用戶可以在創(chuàng)建鏡像時或者運行時傳遞的變量,申明于調用類似于shell中的變量申明與定義。

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}

ENV

ENV指令用來定義鏡像的環(huán)境變量,并且可以引用已經存在的環(huán)境變量,例如:HOME、HOSTNAME、PATH。ENV的值跟ARG指令申明的變量一樣可以傳遞、被引用,定義方法也基本一致。

FROM busybox
ENV foo /bar

# WORKDIR /bar
WORKDIR ${foo}

Dockerfile中的ENV支持以下變量的訪問:ADD、COPY、ENV、EXPOSE、FROM、LABEL、STOPSIGNAL、USER、VOLUME、WORKDIR。

RUN

RUN指令在當前鏡像的頂層中執(zhí)行命令并提交結果,新產生的鏡像用于下一步的Dockerfile。分層執(zhí)行指令和生成提交符號Docker的核心概念,提交很方便,容器可以從鏡像歷史中的任意點創(chuàng)建,類似于源碼控制。在shell形式中,可以使用\(反斜杠)將單個RUN指令繼續(xù)到下一行。RUN指令有兩種使用格式:

RUN <command>(shell形式,該命令在shell中運行,默認情況下/bin/sh -c在Linux中運行,cmd /S /CWindows中運行)
RUN ["executable", "param1", "param2"](exec執(zhí)行形式)
[root@ChatDevOps ~]# cat Dockerfile 
FROM centos
RUN mkdir /chatdevops
RUN ["touch","/chatdevops/chatdevops.log"]
RUN /bin/bash 
[root@ChatDevOps ~]# docker run -it --name chatdevops chatdevops /bin/bash
[root@99484f802e71 /]# ll /chatdevops/chatdevops.log 
-rw-r--r--. 1 root root 0 May 29 03:00 /chatdevops/chatdevops.log

CMD

CMD的主要是為一個正運行的容器提供默認執(zhí)行命令。如果存在多個CMD指令,那么只有最后一個會被執(zhí)行。如果在容器運行時指定了命令,則CMD指定的默認內容會被替代。CMD一共有三種格式:

CMD ["executable","param1","param2"]  #(執(zhí)行形式,這是比較常見的一種形式)
CMD ["param1","param2"] #(以json數組的形式將兩個參數存儲下來,在指定了ENTRYPOINT        指令后,用CMD指定具體的參數,此處必須用雙引號將涉及到的變量引起來)
CMD command param1 param2 #(shell形式)
[root@ChatDevOps ~]# cat Dockerfile 
FROM centos
CMD echo "chatdevops"
CMD ["echo","Hello world"]
[root@ChatDevOps ~]# docker run -it --rm --name chatdevops chatdevops
Hello world

ENTRYPOINT

ENTRYPOINT的格式和RUN指令格式一樣,分為exec格式和shell格式。ENTRYPOINT的目的和CMD一樣,都是在指定容器啟動程序及參數。ENTRYPOINT在運行時 也可以替代,不過比CMD要略顯繁瑣,需要通過docker run的參數--entrypoint來指定。
當指定了ENTRYPOINT后,CMD的含義就發(fā)生了改變,不再是直接的運行其命令,而是將CMD的內容作為參數傳給ENTRYPOINT指令。

[root@ChatDevOps ~]# cat Dockerfile 
FROM ubuntu:18.04
RUN apt-get update \
 && apt-get install -y curl \
 && rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl","-s","http://ip.cn" ]
[root@ChatDevOps ~]# docker run e317e4042076
當前 IP:71.184.25.21 來自:北京市 
[root@ChatDevOps ~]# docker run e317e4042076 -i
HTTP/1.1 200 OK
Date: Tue, 29 May 2018 09:00:10 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: __cfduid=d4439884e43e37c36aac129e9f4d0507f1527584410; expires=Wed, 29-May-19 09:00:10 GMT; path=/; domain=.ip.cn; HttpOnly
Server: cloudflare
CF-RAY: 4227c4e460886d9c-SJC

LABEL

LABEL指令用于添加一個元數據到鏡像,鍵和值配對存在。例如可以給容器添加輔助說明信息。值中支持換行字符斜杠(\)。如果Docker中出現(xiàn)重復的鍵,則新的值會覆蓋原來的值。為了減少Docker的層數,可以在單一LABEL指令中指定多個標簽:

LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"

MAINTAINER

MAINTAINER在新版本中已經廢棄,可以使用LABEL來替代MAINTAINER進行聲明。

EXPOSE

EXPOSE指定容器在運行中監(jiān)聽的端口。默認情況下,EXPOSE指定的是TCP端口,若要指定監(jiān)聽udp端口:

EXPOSE 80/udp

COPY

COPY能夠從構建上下文中復制文件到新的一層中鏡像中,COPY指令有兩種形式:

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

chown屬性只支持Linux容器的構建。COPY命令支持通配符,可以把多個源文件復制到目標文件下。

ADD

ADD的格式和用法基本與COPY一致,并在COPY的基礎上新增了一些功能。ADD的源文件可以是一個URL。如果本地源路徑的文件為一個tar壓縮文件的話,壓縮格式為gzip,bzip2以及xz的情況 下,ADD指令將會自動解壓縮這個壓縮文件到目標路徑,來自于URL的遠程文件則不會被解壓。

VOLUME

VOLUME旨在創(chuàng)建一個具有名稱的掛載點。容器在運行時盡量保持存儲層不發(fā)生數據寫入操作。一個卷可以存在于一個或多個容器的特定目錄,這個目錄可以繞過聯(lián)合文件系統(tǒng),并提供數據共享或數據持久化功能。卷可以在容器間共享或重用,對卷的修改是及時生效的。對卷的修改不會對新的鏡像產生影響,卷會一直存在直到沒有容器使用它??梢允褂脭到M的形式指定多個卷。使用方式如下:

VOLUME /data
VOLUME ["/data"]
VOLUME ["data","test","chatdevops"]

VOLUME也可以在創(chuàng)建容器時進行聲明:

[root@ChatDevOps docker]# docker run -it -v /myvolume --name myvolume  chatdevops

以上命令創(chuàng)建一個名為myvolume的容器,同時掛載/myvolume。/myvolume在之前并不存在,在創(chuàng)建myvolume時同時創(chuàng)建了該目錄。

USER

USER指令為Dockerfile中全部RUN,CMD,ENTRYPOINT設置運行Image時使用的用戶名或UID。這個用戶或組必須事先在系統(tǒng)中存在。若不存在則下一層鏡像以root用戶進行執(zhí)行。

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

WORKDIR

WORKDIR用來為Dockerfile下文中的RUN, CMD, ENTRYPOINT, COPY和ADD等指令指定當前工作目錄。如果存在多個WORKDIR則以指令錢最近的一條為參考。如果該目錄不存在,則系統(tǒng)會自動創(chuàng)建該目錄。如果要改變當前的工作目錄,不能使用cd命令來切換,需要使用WORKDIR來進行切換。

ONBUILD

這是一個特殊的指令,它后面跟的是其它指令,比如 RUN , COPY等,而這些指令,
在當前鏡像構建時并不會被執(zhí)行。只有當以當前鏡像為基礎鏡像,去構建下一級鏡像的時候才會被執(zhí)行。

STOPSIGNAL

STOPSIGNAL指令設置喚醒信號并將其發(fā)送到容器后退出。后跟信號值(無符號整數)或者SIGNAME格式的信號名稱,例如SIGKILL。

STOPSIGNAL signal

HEALTHCHECK

Docker提供了HEALTHCHECK指令,通過該指令指定一行命令,用這行命令來判斷容器主進程的服務狀態(tài)是否還正常,從而比較真實的反應容器實際狀態(tài)。當在一個鏡像指定了HEALTHCHECK指令后,用其啟動容器,初始狀態(tài)會為 starting ,在HEALTHCHECK指令檢查成功后變?yōu)閔ealthy,如果連續(xù)一定次數失敗,則會變?yōu)?br> unhealthy。格式如下:

    HEALTHCHECK [OPTIONS] CMD command (check container health by running a command inside the container)
    HEALTHCHECK NONE (disable any healthcheck inherited from the base image)

HEALTHCHECK 支持下列選項:

  • --interval=<間隔> :兩次健康檢查的間隔,默認為 30 秒;
  • --timeout=<時長> :健康檢查命令運行超時時間,如果超過這個時間,本次健康檢查就被視為失敗,默認 30 秒;
  • --retries=<次數> :當連續(xù)失敗指定次數后,則將容器狀態(tài)視為 unhealthy ,默認3次。

HEALTHCHECK在Dockerfile中只能出現(xiàn)一次,如果出現(xiàn)多次則最后一個生效。

SHELL

SHEELL指令允許默認的shell形式被命令形式覆蓋。在Linux系統(tǒng)中默認shell形式為 [“/bin/sh”, “-c”], 在 Windows上是[“cmd”, “/S”, “/C”]。SHELL指令必須用Dockerfile中的JSON格式寫入。SHELL指令在Windows上特別有用,其中有兩個常用的和完全不同的本機shell:cmd和powershell,以及包括sh的備用shell。 SHELL指令可以出現(xiàn)多次。每個SHELL指令都會覆蓋所有以前的SHELL指令,并影響所有后續(xù)指令。

三、參考文獻

https://docs.docker.com/engine/reference/builder/#usage

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 轉載自 http://blog.opskumu.com/docker.html 一、Docker 簡介 Docke...
    極客圈閱讀 10,719評論 0 120
  • 一、Docker創(chuàng)建鏡像的方式有兩種: 一種通過commit的方式:把做了一系列操作的容器關閉,然后利用docke...
    jie0112閱讀 3,909評論 0 3
  • 昨天下午,天氣還是很熱,很悶,太陽這位最長壽的老公公,依然很是精神抖擻地普照著我們這個南方小城。還好,立秋已過,處...
    綠江南閱讀 346評論 0 0
  • 八 收養(yǎng)成功 本來,就連這衣服也不想要的。畢竟別人穿過,她還是有點潔癖的。但是她卻必須接了,,畢竟是她名正言順的...
    叔夜君閱讀 269評論 0 1
  • 文:二七 不說的理想,才像理想。 ——題記 1 大學時期,看過一段TED演講視...
    克里KELI閱讀 405評論 1 3

友情鏈接更多精彩內容