Docke--Dockerfile指令介紹

Dockerfile 構建鏡像經常使用指令

 Dockerfile 是一個文本文件,其內包含了一條條的指定(Instruction),每一條指令構建一層,所以每一條指定的內容,就是描述該層應當如何構建。html

  經過使用build 命令,根據Dockerfile的描述來構建鏡像mysql

  經過源代碼的方式linux

  經過標準輸入流的方式nginx

經過源代碼的路徑:web

  Dockerfile須要放置在項目的跟目錄位置redis

  在構建的時候,Dockerfile client會把整個context打包發送到Docker Server端,而後由server端負責build鏡像,在構建成功後,會刪除context目錄sql

  docker build -t {鏡像名字} {項目的路徑能夠是相對路徑}docker

經過標準輸入流:shell

  經過標準輸入流的方式獲取Dockerfile的內容數據庫

  client不會打包上傳context目錄,所以對於一些ADD、COPY等涉及host本地文件複製的操做不可以支持

  docker build -t {鏡像名字} - < Dockerfile路徑

已nginx 示例:

[root@server ~]# mkdir myNginx  #建立一個存放Dockerfile的目錄
[root@server ~]# cd myNginx
[root@server myNginx]# vim Dockerfile  #編輯Dockerfile
FROM nginx
RUN echo '<h1>Hello, My Dockerfile Nginx!</h1>' > /usr/share/nginx/html/index.html

這個Dockerfile很簡單,就兩行。涉及到兩條指令,FROM 和RUN。

FROM 指定基礎鏡像

所謂的定製鏡像,必須是以一個鏡像爲基礎,在其上進行定製。一個 Dockerfile 中的 FROM 是必備的指定,而且必須是第一條指令。

FROM {bash鏡像}

RUN 執行命令

RUN 指令是用來執行命令行命令的,一個Dockerfile能夠包含多個 RUN,按照定義順序執行。

RUN 支持兩種運行格式:

  • shell 格式:RUN <cmd>,這個會當作/bin/sh -c 「cmd」 運行,就像直接在命令行中輸入的命令同樣。好比上面的:
    RUN echo '<h1>Hello, My Dockerfile Nginx!</h1>' > /usr/share/nginx/html/index.html
  • exec 格式:RUN ["可執行文件", "參數1", "參數2", ...],Docker 把它當作json的順序來解析,必須使用雙引號,且可執行文件必須是完整路徑。

RUN 就像Shell腳本同樣能夠執行命令,可是也不建議一個命令對應一個RUN,像下面這樣的寫法

FROM centos
RUN yum install -y gcc make cmake
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redi s-3.2.5.tar.gz" 
RUN mkdir -p /usr/src/redis
RUN tar xf redis.tar.gz -C /usr/src/redis --stript-components=1
RUN cd /usr/src/redis
RUN make
RUN make install

 由於Dockerfile 中的每個指令都會創建一層,RUN 也不例外,每個RUN 的行爲,就和咱們手工建立景象的過程同樣,新建一層,上面的這種寫法建立了7層,這樣會產生很是臃腫、很是多層的鏡像,不只僅增長了構建部署的時間,也容易出錯。上面的Dockerfile正確寫法應該以下:

FROM centos
RUN yum install -y gcc make cmake \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redi s-3.2.5.tar.gz"  \
    && mkdir -p /usr/src/redis \
    && tar xf redis.tar.gz -C /usr/src/redis --stript-components=1 \
    && cd /usr/src/redis \
    && make \
    && make install

首先,以前全部的命令只有一個目的,就是編譯、安裝redis 可執行文件。所以沒有必要創建不少層,這只是一層的事情。所以 只須要使用一個RUN 指令,使用&& 將各個所需命令串聯起來。將前面的7層簡化爲1層。

COPY 複製文件

格式:

  • COPY <源路徑> ... <目標路徑>
  • COPY ["<源路徑1>", ... "<目標路徑>"]

 和 RUN 指令同樣,也有兩種格式,一種相似於命令行,一種相似於函數調用。

COPY 指令將從構建上下文目錄中 <源路徑> 的文件/目錄複製到新的一層的鏡像內的 <目標路徑> 位置。例如:

[root@server ~]# mkdir myCentos  #建立一個文件夾
[root@server ~]# cd myCentos/  
[root@server myCentos]# echo "hello world" >> file.txt  #準備測試文件
[root@server myCentos]# mkdir dir  #準備測試目錄
[root@server myCentos]# touch dir/test{1..5}.txt  #準備測試目錄裏面的文件
[root@server myCentos]# vim Dockerfile  #編輯Dockerfile
FROM centos
COPY file.txt /mydir/
COPY dir /mydir/
[root@server myCentos]# ls  #查看宿主主機的當前的測試文件
dir  Dockerfile  file.txt
[root@server myCentos]# ls dir/  #查看宿主機的當前的測試文件
test1.txt  test2.txt  test3.txt  test4.txt  test5.txt
[root@server myCentos]# docker build
-t mycentos:v1 .  #構建一個叫mycentos,標籤爲v1的鏡像 Sending build context to Docker daemon 6.144kB Step 1/3 : FROM centos ---> 1e1148e4cc2c Step 2/3 : COPY file.txt /mydir/ ---> 16250be2483b Step 3/3 : COPY dir /mydir/dir ---> 2296f62ff0b3 Successfully built 2296f62ff0b3 Successfully tagged mycentos:v1 [root@server myCentos]# docker run -it --rm --name myC mycentos:v1 /bin/bash  #啓動一個容器,使用上面建立的鏡像,進去並執行shell命令 [root@cc87d839493f /]# ls mydir/  #查看容器內的mydir文件夾 dir file.txt [root@cc87d839493f /]# ls mydir/dir/  #查看容器內mydir文件夾下面的dir文件夾的文件 test1.txt test2.txt test3.txt test4.txt test5.txt

從上面示例能夠看出, <目標路徑> 能夠是容器內的相對路徑,若是該路徑不存在,會自動在複製文件前建立缺失目錄,且<目標路徑>也能夠是相對路徑(工做目錄能夠用WORKDIR 指令來指定)

若是是拷貝目錄, 那麼在 目標地址 也必須寫上 拷貝的目錄的名稱 。不然是將該目錄下的所文件拷貝到目標路徑

還需注意一點,使用COPY指令,源文件的各類元數據都會保留,好比讀、寫、執行權限、文件變動時間等。這個特性對於鏡像定製頗有用。特別是構建相關的文件都在使用Git進行管理的時候。

ADD 更高級的複製文件

 ADD 指令和COPY 的格式和性質基本一致。可是在 COPY 基礎上增長了一些功能。

好比 <源路徑> 多是一個 URL,這種狀況下,會自動去下載這個連接的文件到 <目標路徑>裏,下載完成的文件權限自動設置爲 600,若是不是想要的權限,那麼能夠經過 RUN 進行權限調整。

若是 <源路徑> 爲一個 tar 壓縮文件的話,或者壓縮格式爲 gzip,bzip以及xz 的狀況下,ADD 指令會自動解壓縮這個壓縮文件到 <目標路徑>去。

示例

[root@server ~]# mkdir myCentos1 && cd myCentos1  #建立構建編寫Dockerfile的目錄並進入
[root@server myCentos1]# wget http://nginx.org/download/nginx-1.14.2.tar.gz  #方便測試,先準備一個nginx1.14-2版本的
[root@server myCentos1]# vim Dockerfile  #編寫Dockerfile
FROM centos
ADD http://nginx.org/download/nginx-1.12.2.tar.gz /nginx/
ADD nginx-1.14.2.tar.gz /nginx/
[root@server myCentos1]# ls   #編寫完成查看當前目錄下的文件
Dockerfile  nginx-1.14.2.tar.gz

[root@server myCentos1]# docker build -t mycentos:v2 .  #開始構建一個名字叫mycentos:v2的鏡像
Sending build context to Docker daemon  1.018MB
Step 1/3 : FROM centos
 ---> 1e1148e4cc2c
Step 2/3 : ADD http://nginx.org/download/nginx-1.12.2.tar.gz /nginx/
Downloading [==================================================>]  981.7kB/981.7kB
 ---> a1c9717e9a03
Step 3/3 : ADD nginx-1.14.2.tar.gz /nginx/
 ---> 068c9e89ae0e
Successfully built 068c9e89ae0e
Successfully tagged mycentos:v2
[root@server myCentos1]# docker run -it --rm --name myC  mycentos:v2 /bin/bash  #進入容器,並執行/bin/bash命令
[root@197da52295fa /]# ls /nginx/  #查看nginx目錄
nginx-1.12.2.tar.gz  nginx-1.14.2

 從上面示例能夠看出,ADD指令,若是咱們跟的是一個URL的文件,那麼會自動下載並放到 <目標路徑>,若是跟的是一個壓縮文件,那麼會自動解壓到 <目標路徑>

注意:若是咱們只是單純的想複製一個文件或者一個壓縮包,那麼建議仍是使用COPY,若是須要像上面這樣用到下載,或解壓縮,採用ADD

CMD 容器啓動命令

容器不是虛擬機,容器就是進程,既然是進程,那麼在啓動容器的時候,須要指定所運行的程序及參數。CMD 指令就是用於指定容器默認的主進程啓動命令的。

CMD 指令有三種格式:

  • shell 格式: CMD <命令>
  • exec 格式:CMD ["可執行文件","參數1","參數2", ...]
  • 參數列表格式:CMD ["參數1","參數2",...] , 這個時候CMD做爲 ENTRYPOINT的參數。

在指令格式上,通常推薦使用exec 格式,這類格式在解析時會被解析爲JSON數組,所以必定要使用雙引號 「」 ,而不要使用單引號。

若是使用shell 格式的話,實際的命令會被包裝爲 sh -c 的參數的形式進行執行。好比:

CMD echo $HOME

在實際執行中,會將其變動爲:

CMD ["sh", "-c", "echo $HOME"]

在運行時能夠指定新的命令來替代鏡像設置中的這個默認命令,好比,centos鏡像默認的 CMD 是 /bin/bash, 若是咱們直接 docker run -it centos 的時候,會直接進入 bash。咱們也能夠在運行時指定別的命令,如 docker run -it centos cat /etc/passwd 。這就是用 cat /etc/passwd命令替換了默認的 /bin/bash 命令了。

前臺執行和後臺執行的問題:
    Docker 不是虛擬機,容器中的應用都應該之前臺執行,而不是像虛擬機、物理機裏面那樣,用 start / systemctl 去啓動後臺服務,容器內沒有後臺服務的概念。
好比:若是咱們將CMD 寫成這樣:
CMD service nginx start
而後會發現容器執行後就馬上退出了,甚至在容器內使用systemctl 命令結果卻發現根本執行不了。這就是由於沒有搞明白前臺、後臺的概念,沒有區分容器和虛擬機的差別,依舊在以傳統虛擬機的角度去理解容器
對於容器而言,其啓動程序就是容器應用進程,容器就是爲了主進程而存在的,主進程退出,容器就失去了存在的意義,從而退出,其它輔助進程不是它須要關心的東西。
而使用 service nginx start 命令,則是但願 start來已後臺守護進程形式啓動nginx服務。而 CMD service nginx start 會被理解爲 CMD ["sh", "-c", "service nginx start"],所以主進程其實是sh, 那麼當service nginx start 命令結束後,sh 也就結束了, sh 做爲主進程退出了,天然就會令容器退出。
正確的作法是直接執行 nginx 可執行文件,而且要求之前臺形式。如:
CMD ["nginx", "-g"," daemon off;"]
理解前臺執行和後臺執行

ENTRYPOINT 入口點

ENTRYPOINT 的格式和 RUN 指令格式同樣,分爲 exec 格式 和shell格式。

ENTRYPOINT 的目的和 CMD 同樣,都是在指定容器啓動程序及參數。ENTRYPOINT 在運行時也能夠替代,不過比CMD要繁瑣,須要經過 docker run 的參數 --entrypoint 來指定。

當指定了 ENTRYPOINT 後,CMD 的含義就發生了改變,再也不是直接運行其命令,而是將 CMD 的內容做爲參數傳給 ENTRYPOINT 指令,換句話說實際執行時,將變爲:

ENTRYPOINT "<CMD>"

那麼問題來了? 有了CMD ,爲何還要有ENTRYPOINT呢? 這種 ENTRYPOINT "<CMD>" 有什麼好處呢?

場景一:讓鏡像變成命令同樣使用

假設咱們須要一個得知本身當前公網IP的鏡像,那麼可使用CMD來實現:

[root@server myCentos2]# cat Dockerfile   #查看Dockerfile文件內容
FROM centos CMD ["curl", "-s", "https://ip.cn"]
[root@server myCentos2]# docker build -t mycentos:v3 .  #建立一個鏡像
[root@server myCentos2]# docker run mycentos:v3  #啓動一個容器
當前 IP: 116.24.66.227 來自: 廣東省深圳市 電信

這樣看起來是能夠當作命令來使用,不過命令通常有參數,CMD 中實質的命令是 curl, 若是但願顯示HTTP頭信息,就須要加上 -i 參數。

[root@server myCentos2]# docker run mycentos:v3 -i
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"-i\": executable file not found in $PATH": unknown.

這裏能夠看到可執行文件找不到的報錯, executable file not found。上面說過,跟在鏡像名後面的是 command, 運行時會替換 CMD 的默認值,所以這裏的 -i 替換了原來的 CMD,而不是添加在原來的 curl -s https://ip.cn 後面,而 -i 根本不是命令,因此找不到。

那麼若是咱們但願加入 -i 參數,咱們就必須從新完整的輸入這個命令:

[root@server myCentos2]# docker run mycentos:v3 curl -i https://ip.cn

顯然這不是好的解決辦法,而是用 ENTRYPOINT 就能夠解決這個問題:

[root@server myCentos2]# cat Dockerfile   #查看修改後的Dockerfile
FROM centos ENTRYPOINT ["curl", "-s", "https://ip.cn"]
[root@server myCentos2]# docker build -t mycentos:v4 .  #再次生成一個新的鏡像
[root@server myCentos2]# docker run mycentos:v4   #測試不加參數啓動鏡像
當前 IP: 116.24.66.227 來自: 廣東省深圳市 電信
[root@server myCentos2]# docker run mycentos:v4 -i   #測試加上參數啓動鏡像
HTTP/1.1 200 OK
Date: Wed, 09 Jan 2019 13:23:09 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: __cfduid=d67dbccf782da9ec6788bf87a78993a701547040189; expires=Thu, 09-Jan-20 13:23:09 GMT; path=/; domain=.ip.cn; HttpOnly
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
CF-RAY: 49673780decb961f-SJC

當前 IP: 116.24.66.227 來自: 廣東省深圳市 電信

從上面能夠看出,不加-i 參數能夠運行成功, 加上-i參數也能夠運行成功,且達到了curl -i 的效果。這是由於當存在 ENTRYPOINT 後,CMD 的內容將會做爲參數傳遞給 ENTRYPOINT ,而這裏 -i 就是新的CMD,所以會做爲參數傳遞給curl,從而達到了咱們預期的效果。

場景二:應用運行前的準備工做

 啓動容器就是啓動主進程,但有些時候,啓動主進程前,須要一些準備工做。好比 mysql 類的數據庫,可能須要一些數據庫配置、初始化的工做,這些工做要在最終的mysql 服務器運行以前解決。此外,可能但願避免使用root 用戶去啓動服務器, 從而提升安全性,而在啓動還須要以 root 身份執行一些必要的準備工做,最後切換到服務用戶啓動服務等。或者除了服務外,其它命令依舊可使用 root 身份執行,方便調試等。

這些準備工做是和容器 CMD 無關的,不管CMD 是什麼,都須要事先進行一個預處理的工做。這種狀況下,能夠寫一個腳本,而後放入 ENTRYPOINT 中去執行,而這個腳本會接到的參數 (也就是CMD)做爲指令,在腳本最後執行。好比官方的redis 中就是這樣作的:

FROM alpine:3.4 
...
RUN addgroup -S redis && adduser -S -G redis redis 
...
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 6379 
CMD ["redis-server"]

能夠看到其中爲了 redis 服務建立了redis 用戶,並在最後指定了 ENTRYPOINT 爲 docker-entrypoint.sh 腳本。

#!/bin/bash
...
# allow the container to be started with `--user` 
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
    chown -R redis .
    exec su-exec redis "$0" "$@"
fi

exec "$@"

該腳本的內容就是根據 CMD 的內容來判斷,若是是 redis-server 的話,則切換到 redis用戶身份啓動服務,不然依舊使用 root 身份執行。好比:

# docker run -it redis id
uid=0(root) gid=0(root) groups=0(root)

ENV 設置環境變量

格式:

  • ENV <key><value>
  • ENV<key1>=<value1> <key2>=<value2>

這個指令很簡單,就是設置環境變量,不管是後面的其它指令,如RUN,仍是運行時的應用,均可以直接使用這裏定義的環境變量。

[root@server myCentos3]# cat Dockerfile   #查看編輯好的Dockerfile文件內容
FROM centos ENV name1 xiaobai ENV name2=zhazha name3=cainiao
[root@server myCentos3]# docker build -t mycentos:v5 .  #構建鏡像
[root@server myCentos3]# docker run --rm -it --name test mycentos:v5  #啓動一個容器,並以交互式啓動 
[root@b55929b2c63f /]# echo $name1  #進入容器後調用環境變量name1
xiaobai
[root@b55929b2c63f /]# echo $name2 $name3  #調用環境變量name2,name3
zhazha cainiao

定義了環境變量,能夠在後續的指令中直接使用環境變量

FROM centos
ENV URL="https://nginx.org/download/" 
ADD $URLnginx.1.12.2.tar.gz /usr/local/

ARG 構建參數

格式:

  • ARG <參數名>[=<默認值>]

構建參數和 ENV的效果同樣,都是設置環境變量。所不一樣的是,ARG 所設置的構建環境和環境變量,在未來容器運行時是不會存在這些環境變量的。可是不要所以就使用 ARG 保存密碼之類的信息,由於 docker history 仍是能夠看到全部值的。

Dockerfile 中的ARG指令是定義參數名稱,以及定義其默認值。該默認值能夠在構建命令 docker build 中用 --build-arg <參數名>=<值> 來覆蓋。

VOLUME 定義匿名卷

格式:

  • VOLUME ["<路徑1>","<路徑2>"...]
  • VOLUME <路徑>

容器運行時應該儘可能保持容器存儲層不會發生寫操做,對於數據庫類須要保存動態數據的應用,其數據文件應該保存在數據卷中,爲了防止運行時忘記將動態文件所保存目錄掛載爲卷,在Dockerfile中,能夠事先指定某些目錄掛載爲匿名卷,這樣在運行時若是用戶不指定掛載,其應用也能夠正常運行,不會向容器存儲層寫入大量數據。

[root@server myCentos4]# cat Dockerfile   #編寫Dockerfile文件,內容以下
FROM nginx VOLUME /usr/share/nginx/html/
[root@server myCentos4]# docker build -t mynginx:v1 .  #建立一個mynginx:v1的鏡像
[root@server myCentos4]# docker run -it --rm --name nginx mynginx:v1 /bin/bash  #利用mynginx:v1鏡像啓動一個名字叫作nginx的容器
root@eaa3ffb6dda7:/# ls /usr/share/nginx/html/  #查看nginx網站目錄的文件
50x.html  index.html

# 此時打開第二個終端,第一個終端不要關閉
[root@server ~]# docker inspect nginx  #在第二個終端查看啓動的nginx 容器掛載信息,會發如今宿主機上面自動掛載到了一個目錄 "Mounts": [
...
                "Source": "/var/lib/docker/volumes/47794aa178f1aa829d8e778f319a6bb678349926a8107f459fcb10d3b00ff8b5/_data",
...
        ],
[root@server ~]# ls /var/lib/docker/volumes/47794aa178f1aa829d8e778f319a6bb678349926a8107f459fcb10d3b00ff8b5/_data  #查看掛載的目錄,和容器中的目錄同樣,有一樣的文件
50x.html  index.html
[root@server ~]# echo "<h1>hello docker</h1>" >> /var/lib/docker/volumes/47794aa178f1aa829d8e778f319a6bb678349926a8107f459fcb10d3b00ff8b5/_data/test.html #在該目錄添加文件

# 此時回到nginx容器啓動的第一個終端
root@eaa3ffb6dda7:/# ls /usr/share/nginx/html/  #再次查看該目錄會發現也有上面新添加的文件
50x.html  index.html  test.html
root@eaa3ffb6dda7:/# cat /usr/share/nginx/html/test.html   #而且查看文件內容 <h1>hello docker</h1>

從上面能夠看出,實際Dockerfile中只作了一件事,那就是將nginx網站目錄掛載到了一個宿主機的一個匿名目錄,且經過 docker inspect能夠找到該目錄,這樣就實現了動態的更改網站數據目錄的內容了。從而提升了靈活性。

一樣還能夠在運行容器的時候指定掛載:

[root@server myCentos4]# docker run -it --rm -v mydata:/usr/share/nginx/html/ --name nginx mynginx:v1 /bin/bash  #指定掛載的目錄啓動容器
root@f5c496cc9846:/# 

# 打開第二個終端查看掛載目錄
[root@server ~]# docker inspect nginx  #查看掛載信息 "Mounts": [
...
                "Source": "/var/lib/docker/volumes/mydata/_data",
                "Destination": "/usr/share/nginx/html",
...
        ],

這樣 使用了 mydata 這個命令卷掛載到了/usr/share/nginx/html 這個位置,替代了Dockerfile 中定義的匿名卷的掛載配置

EXPOSE 聲明端口

格式:

  • EXPOSE <端口1> [<端口2>...]

EXPOSE 指令是聲明運行容器時提供的服務端口,這只是一個聲明,在運行時並不會由於這個聲明就會開啓這個端口的服務。在Dockerfile中寫入這樣的聲明有兩個好處,一個是幫助使用鏡像者理解這個鏡像服務的守護端口,以方便配置映射;另外一個用處則是在運行時使用隨機端口映射時,也就是 docker run -P 時,會自動隨機映射EXPOSE的端口。

WORKDIR 指定工做目錄

格式:

  • WORKDIR <工做目錄路徑>

使用 WORKDIR 指令能夠來制定工做目錄(或者稱爲當前目錄),之後各層的當前目錄就被改成指定的目錄,如該目錄不存在,則會自動建立。

能夠爲RUN、CMD、ENTRYPOINT指令配置工做目錄,可使用多個WORKDIR指令,後續參數若是是相對路徑,則會基於以前的命令指定的路徑。如:WORKDIR /home   WORKDIR test。最終路徑爲/home/test。path路徑也能夠是環境變量,好比有環境變量HOME=/home,   WORKDIR $HOME/test也就是/home/test

[root@server myCentos5]# cat Dockerfile   #查看編輯好的Dockerfile文件
FROM centos
WORKDIR /home/testdir
[root@server myCentos5]# docker build -t mycentos:v6 .  #建立一個名字叫作mycentos:v6的鏡像
[root@server myCentos5]# docker run --rm -it mycentos:v6   #使用上面建立的鏡像啓動一個容器
[root@4f7ae938d471 testdir]# pwd  #進入容器後查看當前工做目錄
/home/testdir

USER 指定當前用戶

格式:

  • USER <用戶名>

USER 和WORKDIR 類似,都是改變環境狀態並影響之後的層。WORKDIR是改變工做目錄,USER 則是指定運行容器時的用戶名或UID,後續的RUN、CMD、ENTRYPOINT 也會已該用戶身份去運行命令。

固然,USER 只是可以切換到指定用戶而已,這個用戶必須事先創建好,不然沒法切換。

RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN ["redis-server"]

HEALTHCHECK 健康檢查

格式:

  • HEALTHCHECK [選項] CMD <命令>:設置檢查容器健康的命令
  • HEALTHCHECK NONE:若是基礎鏡像有健康檢查指令,使用這行能夠屏蔽掉其健康檢查指令

HEALTHCHECK 指令是告訴Docker 應該如何進行判斷容器的狀態是否正常

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

HEALTHCHECK 支持下列選項:

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

和CMD, ENTRYPOINT  同樣,HEALTHCHECK 只能夠出現一次,若是寫了多個,只有最後一個生效。

在HEALTHCHECK [選項] CMD 後面的命令,格式和  ENTRYPOINT  同樣,分爲 shell  格式,和 exec 格式。命令的返回值決定了該次健康檢查的成功與 否:0:成功; 1 :失敗; 2  :保留,不要使用這個值。
假設咱們有個鏡像是個最簡單的    Web    服務,咱們但願增長健康檢查來判斷其    Web 服務是否在正常工做,咱們能夠用  curl 來幫助判斷,其 Dockerfile  的  HEALTHCHECK能夠這樣寫:

[root@server myNginx1]# cat Dockerfile 
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
    CMD curl -fs http://localhost/ || exit 1
[root@server myNginx1]# docker build -t mynginx:v2 .
[root@server myNginx1]# docker run -d --name web -p 80:80 mynginx:v2

這裏設置了每5秒檢查一次(這裏爲了測試因此間隔很是短,實際應該相對較長),若是健康檢查命令超過3秒沒響應就視爲失敗,而且使用 curl -fs http://localhost/ || exit 1 做爲健康檢查命令。

當運行改鏡像啓動的容器後,能夠經過 docker ps 看到最初的狀態爲(health:starting):

[root@server myNginx1]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                            PORTS                NAMES
fb9c72f7a6de        mynginx:v2          "nginx -g 'daemon of…"   6 seconds ago       Up 4 seconds (health: starting)   0.0.0.0:80->80/tcp   web

 再等待幾秒鐘後,再次 docker ps,就會看到健康檢查狀態變成了 (healthy):

[root@server myNginx1]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS                NAMES
fb9c72f7a6de        mynginx:v2          "nginx -g 'daemon of…"   18 seconds ago      Up 17 seconds (healthy)   0.0.0.0:80->80/tcp   web

若是健康檢查連續失敗超過了重試次數,狀態就會變爲 (unhealthy)。

相關文章
相關標籤/搜索