004.Docker鏡像管理

一 鏡像基本操做

鏡像是一個包含程序運行必要依賴環境和代碼的只讀文件,其本質是磁盤上一系列文件的集合。它採用分層的文件系統,將每一次改變以讀寫層的形式增長到原來的只讀文件上。鏡像是容器運行的基石。

1.1 搜索鏡像

  1 root@docker:~# docker search centos				#查詢centos共享鏡像
01
docker命令必須具有root權限,普通用戶但是用那個sudo。
提示:docker默認的Docker Hub 網址爲: https://hub.docker.com/,速度很慢,建議添加國內的阿里雲加速器,參考004-4.1。
選項說明:
NAME:鏡像倉庫源的名稱
DESCRIPTION:鏡像的描述
OFFICIAL:是否docker官方發佈
AUTOMATED:是否使用了自動構建

1.2 下載(拉取)鏡像

  1 root@docker:~# docker pull centos:7				#使用pull下載鏡像
02
提示:
Registry:倉庫,Registry包含一個或多個Repository
Repository:系列,Repository包含一個或多個Image
Tag and Image:Image用GUID表示,有一個或多個Tag與之關聯,版本號。

1.3 列出(查看)本地鏡像

  1 root@docker:~# docker images 	<特定標籤>			#查看本地下載的鏡像
03
選項說明:
  • REPOSTITORY:表示鏡像的倉庫源,有如下類型:
    • [namespace/centos]:由命名空間和實際的倉庫名稱組成。
    • [centos]:只有倉庫名。屬於頂級命名空間,只用於官方鏡像。
    • [dl.dockerpool.com:5000\centos:7]:指定URL路徑的方式。
  • TAG:鏡像的標籤
    • 未指定鏡像tag時,默認爲latest,但latest沒有任何特殊含義,人爲的將latest做爲最新穩定版本的別名;
    • 一個repository能夠有多個tag,而多個tag也可能對應同一個鏡像。
  • IMAGE ID:鏡像ID
  • CREATED:鏡像建立時間
  • SIZE:鏡像大小

1.4 推送鏡像

  1 root@docker:~# docker push registry.cn-hangzhou.aliyuncs.com/xhy-study-01/xhy-images-01:centos-7-xhy
04
提示:推送鏡像以前必須配置好倉庫信息。建議推送至我的私有倉庫,同時採用國內阿里雲私有倉庫,配置方法見《附001-docker阿里雲Registry配置》。

1.5 導出鏡像

  1 root@docker:~# docker save -o centos-7.tar centos:7

1.6 導入鏡像

  1 root@docker:~# docker load -i centos-7.tar

1.7 刪除鏡像

  1 root@docker:/study# docker rmi httpd

1.8 設置鏡像標籤

  1 root@docker:~# docker tag 6de222aa7640 xhy/centos7:v3
  2 root@docker:~# docker images
05

二 docker文件系統

2.1 Linux文件系統簡介

linux文件系統由bootfs和rootfs組成,bootfs主要包含bootloader和kernel,bootloader主要是引導加載kernel,當kernel被加載到內存以後bootfs就被卸載掉了。rootfs包含的就是典型linux系統中/dev,/proc,/bin,/etc等標準目錄。

2.2 docker文件系統

Docker容器是創建在Aufs基礎上的,Aufs支持將不一樣的目錄掛載到同一個虛擬文件系統下,並實現一種layer的概念。Aufs將掛載到同一虛擬文件系統下的多個目錄分別設置成read-only,read-write以及whiteout-able權限。
read-only目錄只能讀,而寫操做只能在read-write目錄中實現。
寫操做是在read-only之上的一種增量操做,不影響read-only目錄。
docker 鏡像中每一層文件系統都是read-only。
提示:當掛載目錄的時候要嚴格按照各目錄之間的這種增量關係,將被增量操做的目錄優先於在它基礎上增量操做的目錄掛載,待全部目錄掛載結束了,繼續掛載一個read-write目錄,如此便造成了一種層次結構。

2.3 docker鏡像原理

在構建鏡像時,從一個最基本的操做系統開始,每一個構建的操做都至關於作一層修改,增長了一層文件系統,一層層往上疊加,上層的修改會覆蓋底層該位置的可見性。當使用時,只會看到一個徹底的總體,總共有多少層以及每層所作的修改都是透明的。
06
docker image 中最基礎的兩層結構:
07
不一樣的 linux 發行版(如 ubuntu 和 CentOS ) 在 rootfs 這一層會有所區別,體現發行版本的差別性:
08
傳統的 Linux 加載 bootfs 時會將 rootfs 設爲 read-only,而後在系統自檢後將 rootfs 從 read-only改成 read-write,而後可在 rootfs 上進行讀寫操做。
Docker相比在 bootfs 自檢完畢以後不會將 rootfs 的 read-only 改成 read-write,而是利用 union mount(UnionFS 的一種掛載機制)將 image 中其餘的 layer 加載到以前的 read-only 的 rootfs 層之上,每一層 layer 都是 rootfs 的結構,而且是read-only 的。所以,沒法修改一個已有鏡像裏面的 layer層數據,只有當建立一個容器,即將 Docker 鏡像進行實例化後,系統會分配一層空的 read-write 的 rootfs ,用於提供數據修改。

三 鏡像結構

3.1 image結構

09
docker image的layer組織方式一般由 json、layer.tar、VERSION組成。
  1 root@docker:/study# tar -xf centos-7.tar
10
  1 root@docker:/study# tree
11
  1 root@docker:/study# cat repositories
  2 {"centos":{"7":"d1ed0d8ec4ec460641430566e9a8cece698e60d4ad4afcf48759ad157d340064"}}
解釋:repositories 文件,裏面是一個 JSON 定義,保存了三個信息:鏡像名字、tag、tag 對應的 layer。
  1 root@docker:/study# cat d1ed0d8ec4ec460641430566e9a8cece698e60d4ad4afcf48759ad157d340064/json | jq .
12
解釋:主要關於鏡像的配置信息,簡要部分信息如上。
  1 root@docker:/study# tar -tf d1ed0d8ec4ec460641430566e9a8cece698e60d4ad4afcf48759ad157d340064/layer.tar
13
解釋:包括一個類 Linux 文件目錄的結構,保存着這個 layer 所作的修改。

四 Dockerfile、Docker鏡像和Docker容器

4.1 關係

Dockerfile 是軟件的原材料,Docker 鏡像是軟件的交付品,而 Docker 容器則能夠認爲是軟件的運行態。從應用軟件的角度來看,Dockerfile、Docker 鏡像與 Docker 容器分別表明軟件的三個不一樣階段,Dockerfile 面向開發,Docker 鏡像成爲交付標準,Docker 容器則涉及部署與運維。
14
Dockerfile構建出Docker鏡像,經過Docker鏡像運行Docker容器。
15
參考連接:http://dockone.io/article/783
https://blog.csdn.net/xuguokun1986/article/details/79295947

五 docker存儲驅動

Docker最開始採用AUFS做爲文件系統,也得益於AUFS分層的概念,實現了多個Container能夠共享同一個image。但因爲AUFS未併入Linux內核,且只支持Ubuntu,考慮到兼容性問題,在Docker 0.7版本中引入了存儲驅動, 目前,Docker支持AUFS、Btrfs、Device mapper、OverlayFS、ZFS五種存儲驅動。

5.1 底層技術

  • 寫時複製(CoW)
全部驅動都須要用到寫時複製(CoW),CoW就是copy-on-write,表示只在須要寫時纔去複製,這個是針對已有文件的修改場景。好比基於一個image啓動多個Container,若是爲每一個Container都去分配一個image同樣的文件系統,那麼將會佔用大量的磁盤空間。而CoW技術可讓全部的容器共享image的文件系統,全部數據都從image中讀取,只有當要對文件進行寫操做時,才從image裏把要寫的文件複製到本身的文件系統進行修改。
因此不管有多少個容器共享同一個image,所作的寫操做都是對從image中複製到本身的文件系統中的複本上進行,並不會修改image的源文件,且多個容器操做同一個文件,會在每一個容器的文件系統裏生成一個複本,每一個容器修改的都是本身的複本,相互隔離,相互不影響。使用CoW能夠有效的提升磁盤的利用率。
  • 用時分配(allocate-on-demand)
用時分配是用在本來沒有這個文件的場景,只有在要新寫入一個文件時才分配空間,這樣能夠提升存儲資源的利用率。好比啓動一個容器,並不會爲這個容器預分配一些磁盤空間,而是當有新文件寫入時,才按需分配新空間。

5.2 AUFS

AUFS(AnotherUnionFS)是一種Union FS,是文件級的存儲驅動。AUFS能透明覆蓋一個或多個現有文件系統的層狀文件系統,把多層合併成文件系統的單層表示。即支持將不一樣目錄掛載到同一個虛擬文件系統下的文件系統。
這種文件系統能夠一層一層地疊加修改文件。不管底下有多少層都是隻讀的,只有最上層的文件系統是可寫的。當須要修改一個文件時,AUFS建立該文件的一個副本,使用CoW將文件從只讀層複製到可寫層進行修改,結果也保存在可寫層。
在Docker中,底下的只讀層就是image,可寫層就是Container。結構以下圖所示:
16

5.3 OverlayFS

Overlay是Linux內核3.18後支持的,也是一種Union FS,和AUFS的多層不一樣的是Overlay只有兩層:一個upper文件系統和一個lower文件系統,分別表明Docker的鏡像層和容器層。當須要修改一個文件時,使用CoW將文件從只讀的lower複製到可寫的upper進行修改,結果也保存在upper層。在Docker中,底下的只讀層就是image,可寫層就是Container。
17

5.4 Device mapper

Device mapper是Linux內核2.6.9後支持的,提供的一種從邏輯設備到物理設備的映射框架機制,在該機制下,用戶可根據須要制定實現存儲資源的管理策略。
不一樣於AUFS和OverlayFS的文件級存儲,Device mapper是塊級存儲,全部的操做都是直接對塊進行操做,而不是文件。
Device mapper驅動會先在塊設備上建立一個資源池,而後在資源池上建立一個帶有文件系統的基本設備,全部鏡像都是這個基本設備的快照,而容器則是鏡像的快照。
因此在容器裏看到文件系統是資源池上基本設備的文件系統的快照,並不有爲容器分配空間。當要寫入一個新文件時,在容器的鏡像內爲其分配新的塊並寫入數據,即用時分配。當要修改已有文件時,再使用CoW爲容器快照分配塊空間,將要修改的數據複製到在容器快照中新的塊裏再進行修改。
Device mapper 驅動默認會建立一個100G的文件包含鏡像和容器。每個容器被限制在10G大小的卷內,大小可配置調整。
18

5.5 Btrfs

Btrfs被稱爲下一代寫時複製文件系統,併入Linux內核,也是文件級級存儲,但能夠像Device mapper直接操做底層設備。
Btrfs把文件系統的一部分配置爲一個完整的子文件系統,稱之爲subvolume 。那麼採用 subvolume,一個大的文件系統能夠被劃分爲多個子文件系統,這些子文件系統共享底層的設備空間,在須要磁盤空間時便從底層設備中分配。
爲了靈活利用設備空間,Btrfs 將磁盤空間劃分爲多個chunk 。每一個chunk可使用不一樣的磁盤空間分配策略。好比某些chunk只存放metadata,某些chunk只存放數據。這種模型有不少優勢,好比Btrfs支持動態添加設備。
用戶在系統中增長新的磁盤以後,可使用Btrfs的命令將該設備添加到文件系統中。
Btrfs把一個大的文件系統當成一個資源池,配置成多個完整的子文件系統,還能夠往資源池裏加新的子文件系統,而基礎鏡像則是子文件系統的快照,每一個子鏡像和容器都有本身的快照,這些快照則都是subvolume的快照。
當寫入一個新文件時,爲在容器的快照裏爲其分配一個新的數據塊,文件寫在這個空間裏,這個叫用時分配。而當要修改已有文件時,使用CoW複製分配一個新的原始數據和快照,在這個新分配的空間變動數據,變結束再更新相關的數據結構指向新子文件系統和快照,原來的原始數據和快照沒有指針指向,被覆蓋。
19

5.6 ZFS

ZFS 文件系統是一個革命性的全新的文件系統,它從根本上改變了文件系統的管理方式,ZFS 徹底拋棄了「卷管理」,再也不建立虛擬的卷,而是把全部設備集中到一個存儲池中來進行管理,用「存儲池」的概念來管理物理存儲空間。過去,文件系統都是構建在物理設備之上的。爲了管理這些物理設備,併爲數據提供冗餘,「卷管理」的概念提供了一個單設備的映像。而ZFS建立在虛擬的,被稱爲「zpools」的存儲池之上。每一個存儲池由若干虛擬設備(virtual devices,vdevs)組成。這些虛擬設備能夠是原始磁盤,也多是一個RAID1鏡像設備,或是非標準RAID等級的多磁盤組。因而zpool上的文件系統可使用這些虛擬設備的總存儲容量。
20
Docker裏ZFS的使用。首先從zpool裏分配一個ZFS文件系統給鏡像的基礎層,而其餘鏡像層則是這個ZFS文件系統快照的克隆,快照是隻讀的,而克隆是可寫的,當容器啓動時則在鏡像的最頂層生成一個可寫層。以下圖所示:
21
當要寫一個新文件時,使用按需分配,一個新的數據快從zpool裏生成,新的數據寫入這個塊,而這個新空間存於容器(ZFS的克隆)裏。
當要修改一個已存在的文件時,使用寫時複製,分配一個新空間並把原始數據複製到新空間完成修改。

5.7 存儲驅動的對比及適應場景

 
特色
優勢
缺點
使用場景
AUFS
聯合文件系統
未併入內核主線
文件級存儲
做爲docker的第一個存儲驅動,相對穩定,且在大量的生產中實踐,有較強的社區支持。
有多層,在作寫時複製操做時,若是文件較大且存在比較低的層,可能會慢一些。
大併發但少IO的場景。
OverlayFS
聯合文件系統
併入內核主線
文件級存儲
只有兩層
無論修改的內容大小都會複製整個文件,對大文件進行修改顯示要比小文件消耗更多的時間。
大併發但少IO的場景。
Device mapper
併入內核主線
塊級存儲
塊級不管是大文件仍是小文件都只複製須要修改的塊,並非整個文件。
不支持共享存儲,即有多個容器讀同一個文件時,須要生產多個副本,在多容器啓停的狀況下可能會致使磁盤溢出。
適合IO密集的場景。
Btrfs
併入內核主線
文件級存儲
可如Device mapper直接操做底層設備,支持動態添加設備。
不支持共享存儲,即有多個容器讀同一個文件時,須要生產多個副本,在多容器啓停的狀況下可能會致使磁盤溢出。
不適合在高密度容器的PaaS平臺上使用。
ZFS
把全部設備密集到一個存儲池進行管理。
支持多個容器共享一個緩存塊,適合內存大的環境。
COW使碎片化問題更加嚴重,文件在硬盤上的物理地址會變得再也不連續,順序讀會變得性能比較差。
適合PaaS和高密度的場景。
參考連接:http://dockone.io/article/1513

5.8 修改docker存儲驅動類型

  1 root@docker:~# vi /etc/docker/daemon.json
  2 {
  3 "storage-driver": "overlay2"
  4 }

六 建立鏡像

從鏡像倉庫中下載的鏡像若不能知足需求,可經過如下兩種方式對鏡像進行更改。
  • 從已經建立的容器中更新鏡像,而且提交這個鏡像
  • 使用 Dockerfile 指令來建立一個新的鏡像

6.1 更新鏡像並提交

  1. 運行容器
  2. 修改容器
  3. 將容器保存爲新的鏡像
  1 root@docker:~# docker run --name centos-7-01 -it centos:7 /bin/bash	#建立容器
  2 [root@01b2b251e216 /]# yum -y install net-tools vim openssh-clients wget ntp bash-completion    #安裝軟件
  3 [root@01b2b251e216 /]# exit
  4 root@docker:~# docker commit -m="has modify" -a="xhy" 01b2b251e216 centos-7-01
  5 root@docker:~# docker images
22
參數說明:
  • -m:提交的描述信息
  • -a:指定鏡像做者
  • 01b2b251e216 :容器ID
  • centos-7-01:指定要建立的目標鏡像名
  1 root@docker:~# docker images						#查看鏡像
更新現有鏡像缺陷
  • 手動建立,容易出錯,效率低及可重複性弱
  • 使用者並不知道鏡像是如何建立出來的,裏面是否有惡意程序,可能存在案例隱患

6.2 Dockerfile構建鏡像舉例

  1 root@docker:~# mkdir /dockerfiles
  2 root@docker:~# cd /dockerfiles/
  3 root@docker:/dockerfiles# vi Dockerfile
  4 FROM            centos:7
  5 MAINTAINER  Fisher "xhy@imxhy.cn"
  6 
  7 RUN         /bin/echo 'root:x123456' |chpasswd
  8 RUN         useradd xhy
  9 RUN         /bin/echo 'xhy:x123456' |chpasswd
 10 RUN         /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
 11 EXPOSE      22
 12 EXPOSE      80
 13 CMD         /usr/sbin/sshd -D
語句說明:
第一條FROM,指定所採用的鏡像源,每個指令的前綴都必須是大寫的;
RUN 指令表示docker在鏡像內執行的命令,更多詳見七Dockerfile詳解。
  1 root@docker:/dockerfiles# docker build -t xhy/centos7 /dockerfiles/
參數說明:
  • -t :指定要建立的目標鏡像名
  • /dockerfiles/:Dockerfile 文件所在目錄
  1 root@docker:~# docker images						#查看鏡像
23
  1 root@docker:/dockerfiles# docker run -t -i xhy/centos7  /bin/bash	#建立容器
24

七 Dockerfile詳解

7.1 Dockerfile典型結構

  1 From ubutu						#第一行必須指令基於的基礎鏡像
  2 MAINTAINER docker_user  docker_user@mail.com        #維護者信息
  3 apt/sourcelist.list					#鏡像的操做指令
  4 RUN apt-get update && apt-get install -y ngnix 	#鏡像的操做指令
  5 RUN echo "\ndaemon off;">>/etc/ngnix/nignix.conf	#鏡像的操做指令
  6 CMD /usr/sbin/ngnix					#容器啓動時執行指令

7.2 Dockerfile相關指令

  • 指令:From
語法:
  1 FROM <image>
  2 FROM <image>:<tag>
  3 FROM <image>:<digest>

含義:FROM命令定義構建鏡像的基礎鏡像,該條必須是dockerfile的首個命令。若同一個DockerFile建立多個鏡像時,可以使用多個From指令(每一個鏡像一次),FROM 是必備且必須是第一條指令。在FROM指定構建鏡像的基礎源鏡像時,若本地沒有指定的該鏡像,則會自動從 Docker 的公共庫 pull 鏡像下來。
提示:
  • FROM必須是 Dockerfile 中非註釋行的第一個指令,即一個 Dockerfile 從FROM語句開始。
  • 若是有需求在一個 Dockerfile 中建立多個鏡像,則FROM能夠在一個 Dockerfile 中出現屢次。
  • 若是FROM語句沒有指定鏡像標籤,則默認使用latest標籤。
舉例:FROM ubuntu
  • 指令:MAINTAINER
語法:
  1 MAINTAINER <name>
含義:聲明做者信息,能夠放在文件任何位置,建議放在FROM後面。
舉例:
  1 MAINTAINER  xhy
  • 指令:RUN
語法:
  1 RUN <commands>
  2 RUN "executable", "param1", "param2"

含義:RUN 指令是用來執行命令行命令的,每條RUN指令將在當前鏡像基礎上執行指定命令,並提交爲新的鏡像,後續RUN都在以前RUN提交後的鏡像爲基礎.
exec 方式會被解析爲一個 JSON 數組,因此必須使用雙引號而不是單引號。exec 方式不會調用一個命令 shell,因此也就不會繼承相應的變量,RUN產生的緩存在下一次構建的時依舊有效,且會被重用,可使用--no-cache選項,即docker build --no-cache,如此便不會緩存。
舉例:
  1 RUN echo 'Hello, Docker!'
  2 RUN ["/bin/bash", "-c","echo hello"]

提示:對於處理同一事件的多個命令,建議採用&&鏈接爲一個命令,即構建一層便可。命令過長可以使用\的換行方式。
  • 指令:CMD
語法:
  1 CMD "executable","param1","param2"
  2 CMD "param1","param2"
  3 CMD command param1 param2 (shell form)

含義:CMD配置在啓動容器時提供一個默認的命令執行選項,若是用戶啓動容器時指定了運行的命令,則會覆蓋掉CMD指定的命令。
舉例:
提示:在容器運行時可指定新的命令來替代鏡像設置的默認命令,如ubuntu鏡像默認的CMD是/bin/bash,直接docker run -it ubuntu則會進入bash。若在運行時指定其餘的命令,如docker run -it ubuntu cat /etc/os-release 。則使用cat /etc/os-release命令替換默認/bin/bash命令。
注意:CMD會在啓動容器的時候執行,build 時不執行,而RUN只是在構建鏡像的時候執行。
  • 指令:ENTRYPOINT
語法:
  1 ENTRYPOINT "executable", "param1", "param2"
  2 ENTRYPOINT command param1 param2 (shell form)

含義:ENTRYPOINT配置容器啓動後執行的命令,而且不可被 docker run 提供的參數覆蓋,區別於CMD是能夠被覆蓋的。若須要ENTRYPOINT被覆蓋,則可使用docker run --entrypoint選項。
舉例:
  1 ENTRYPOINT ["nginx"]
  2 CMD ["-g","daemon off;"]
注意:每一個 Dockerfile 中只能有一個ENTRYPOINT,當指定多個時,只有最後一個生效;
當指定了 ENTRYPOINT 後, CMD 再也不是直接的運行其命令,而是將CMD 的內容做爲參數傳給 ENTRYPOINT 指令,即:<ENTRYPOINT> "<CMD>"
  • 指令:ADD
語法:
  1 ADD <src>... <dest>
含義:複製本地主機、url或啓動配置上下文中的文件到容器指定路徑中 。
舉例:
  1 ADD http://mirrors.163.com/.help/CentOS7-Base-163.repo /etc/yum.repos.d/CentOS-Base.repo
提示:若 <src> 是一個 URL ,構建鏡像時會下載這個連接的文件放至 <dest> ,下載後權限爲 600;
若傳入dest的是個tar壓縮包,壓縮格式爲 gzip、bzip2 以及 xz 的狀況下, ADD 指令將會自動解壓縮這個壓縮文件至 <dest> 。所以若只是複製個壓縮文件進去,而不解壓縮,建議使用copy;
ADD 指令會令鏡像構建緩存失效,從而可能會令鏡像構建變得比較緩慢。
  • 指令:COPY
語法:
  1 COPY <src>... <dest>
含義:複製新文件或者目錄從 而且添加到容器指定路徑中 ,用法參考ADD,但COPY不能指定遠程文件 URLS。
舉例:
  1 COPY package.json /usr/src/app/
建議:在 COPY 和 ADD 指令中選擇的時候,能夠遵循這樣的原則,全部的文件複製均使用 COPY 指令,僅在須要自動解壓縮的場合使用 ADD 。
  • 指令:EXPOSE
語法:
  1 EXPOSE <port> [<port>...]
含義:聲明Docker服務端容器對外監聽的端口,須要同時在docker run 的時候使用-p或者-P選項生效,默認爲TCP。
舉例:
  1 EXPOSE 22 80 8443
  • 指令:ENV
語法:
  1 ENV <key> <value>       # 只能設置一個變量
  2 ENV <key>=<value> ...   # 容許一次設置多個變量
含義:指定一個環節變量,會被後續RUN指令使用,並在容器運行時保留。
舉例:
  1 ENV myName="John Doe" myDog=Rex myCat=fluffy
  2 ENV PG_MAJOR 9.3
  3 ENV PG_VERSION 9.3.4

  • 指令:VOLUME
語法:
  1 VOLUME ["<路徑1>", "<路徑2>"...]
  2 VOLUME <路徑>

含義:卷分爲宿主目錄、數據卷、容器卷。VOLUME命令會設置掛載點,在啓動容器的時候Docker會在/var/lib/docker/的下一級目錄下建立一個卷,通常用來存放動態數據和須要保持的數據等。
舉例:
  1 VOLUME ["/data","/opt"]
  • 指令:WORKDIR
語法:
  1 WORKDIR <path>
含義:使用 WORKDIR 指令能夠來指定工做目錄(或者稱爲當前目錄),以後各層的當前目錄就被改成指定的目錄,如該目錄不存在, WORKDIR 會幫你創建目錄,在使用 docker run 命令啓動容器時,默認會進入的目錄是 WORKDIR 指定的目錄。
舉例:
  1 WORKDIR /app
  • 指令:USER
語法:
  1 USER <user>[:<group>]
  2 USER <UID>[:<GID>]

含義:指定運行容器時的用戶名或UID,後續的 RUN 也會使用指定用戶。當服務不須要管理員權限時,能夠經過該命令指定運行用戶。
舉例:
  1 RUN groupadd -r redis && useradd -r -g redis redis
  2 USER redis
  3 RUN [ "redis-server" ]
提示:WORKDIR 是改變工做目錄, USER 則是改變以後層的執行 RUN , CMD 以及 ENTRYPOINT 這類命令的身份。
  • 指令:ONBUILD
語法:
  1 ONBUILD [INSTRUCTION]
含義:ONBUILD 是一個特殊的指令,ONBUILD 後是其它指令,好比 RUN , COPY 等,而此類指令,在當前鏡像構建時並不會被執行。只有當以當前鏡像爲基礎鏡像,去構建下一個鏡像的時候纔會被執行。即配置當該鏡像做爲其它新建立鏡像的基礎鏡像時,所執行的操做指令。
舉例:Dockerfile-01使用以下的內容建立了鏡像image-A:
  1 [...]
  2 ONBUILD ADD . /app/src
  3 ONBUILD RUN /usr/local/bin/python-build --dir /app/src
  4 [...]
Dockerfile-02使用基於image-A的基礎鏡像建立image-B:
  1 FROM image-A
Dockerfile-02的內容等同於:
  1 ADD . /app/src
  2 RUN /usr/local/bin/python-build --dir /app/src
  • 指令:HEALTHCHECK
語法:
  1 HEALTHCHECK [選項] CMD <命令> :設置檢查容器健康情況的命令
  2 HEALTHCHECK NONE :若是基礎鏡像有健康檢查指令,使用這行能夠屏蔽掉其健康檢查指令

含義:HEALTHCHECK 指令用於判斷Docker容器的狀態是否正常。
選項:
HEALTHCHECK 支持下列選項:
    • interval=<間隔> :兩次健康檢查的間隔,默認爲 30 秒;
    • timeout=<時長> :健康檢查命令運行超時時間,若是超過這個時間,本次健康檢查就被視爲失敗,默認 30 秒;
    • retries=<次數> :當連續失敗指定次數後,則將容器狀態視爲 unhealthy ,默認 3 次。
舉例:
  1 FROM nginx
  2 RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
  3 HEALTHCHECK --interval=5s --timeout=3s \
  4 CMD curl -fs http://localhost/ || exit 1

設置了每 5 秒檢查一次,若是健康檢查命令超過 3 秒沒響應就視爲失敗,而且使用 curl -fs http://localhost/ || exit 1 做爲健康檢查命令。
提示:相似CMD , ENTRYPOINT 同樣, HEALTHCHECK 也只能夠出現一次,若存在多個HEALTHCHECK,只有最後一個生效。
參考連接:https://blog.csdn.net/wo18237095579/article/details/80540571

7.3 dockerfile最佳實踐

  • 使用.dockerignore文件
爲在docker build過程當中更快上傳和更加高效,可以使用一個.dockerignore文件用來排除構建鏡像時不須要的文件或目錄。
  • 避免安裝沒必要要的軟件包
爲了下降複雜性、依賴性、文件大小以及構建時間,應該避免安裝額外的或沒必要要的包。
  • 每一個容器都跑一個進程
在大多數狀況下,一個容器應該只單獨跑一個程序。解耦應用到多個容器使其更容易橫向擴展和重用。
  • 最小化層
每執行一個指令,都會有一次鏡像的提交,鏡像是分層的結構,對於Dockerfile,應該找到可讀性和最小化層之間的平衡。
  • 多行參數排序
若是可能,經過字母順序來排序,這樣能夠避免安裝包的重複而且更容易更新列表,另外可讀性也會更強,添加一個空行使用\換行:
  1 RUN apt-get update && apt-get install -y \
  2   bzr \
  3   cvs \
  4   git \
  5   mercurial \
  6   subversion
  • 儘量清理沒必要要的文件
使構建後的鏡像儘量的小。
相關文章
相關標籤/搜索