1. 程式人生 > >004.Docker映象管理

004.Docker映象管理

一 映象基本操作

映象是一個包含程式執行必要依賴環境和程式碼的只讀檔案,其本質是磁碟上一系列檔案的集合。它採用分層的檔案系統,將每一次改變以讀寫層的形式增加到原來的只讀檔案上。映象是容器執行的基石。

1.1 搜尋映象

  1 [email protected]:~# docker search centos				#查詢centos共享映象
15 docker命令必須具備root許可權,普通使用者可是用那個sudo。 提示:docker預設的Docker Hub 網址為: https://hub.docker.com/,速度很慢,建議新增國內的阿里雲加速器,參考004-4.1。
選項說明: NAME:映象倉庫源的名稱 DESCRIPTION:映象的描述 OFFICIAL:是否docker官方釋出 AUTOMATED:是否使用了自動構建

1.2 下載(拉取)映象

  1 [email protected]:~# docker pull centos:7				#使用pull下載映象
16 提示: Registry:倉庫,Registry包含一個或多個Repository Repository:系列,Repository包含一個或多個Image Tag and Image:Image用GUID表示,有一個或多個Tag與之關聯,版本號。

1.3 列出(檢視)本地映象

  1 [email protected]:~# docker images 	<特定標籤>			#檢視本地下載的映象
17 選項說明:
  • 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 [email protected]:~# docker push registry.cn-hangzhou.aliyuncs.com/xhy-study-01/xhy-images-01:centos-7-xhy
18 提示:推送映象之前必須配置好倉庫資訊。建議推送至個人私有倉庫,同時採用國內阿里雲私有倉庫,配置方法見《附001-docker阿里雲Registry配置》。

1.5 匯出映象

  1 [email protected]:~# docker save -o centos-7.tar centos:7

1.6 匯入映象

  1 [email protected]:~# docker load -i centos-7.tar

1.7 刪除映象

  1 [email protected]:/study# docker rmi httpd

1.8 設定映象標籤

  1 [email protected]:~# docker tag 6de222aa7640 xhy/centos7:v3
  2 [email protected]:~# docker images
19

二 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映象原理

在構建映象時,從一個最基本的作業系統開始,每個構建的操作都相當於做一層修改,增加了一層檔案系統,一層層往上疊加,上層的修改會覆蓋底層該位置的可見性。當使用時,只會看到一個完全的整體,總共有多少層以及每層所做的修改都是透明的。 20 docker image 中最基礎的兩層結構: 21 不同的 linux 發行版(如 ubuntu 和 CentOS ) 在 rootfs 這一層會有所區別,體現發行版本的差異性: 22 傳統的 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結構

23 docker image的layer組織方式通常由 json、layer.tar、VERSION組成。
  1 [email protected]:/study# tar -xf centos-7.tar
24
  1 [email protected]:/study# tree
25
  1 [email protected]:/study# cat repositories
  2 {"centos":{"7":"d1ed0d8ec4ec460641430566e9a8cece698e60d4ad4afcf48759ad157d340064"}}
解釋:repositories 檔案,裡面是一個 JSON 定義,儲存了三個資訊:映象名字、tag、tag 對應的 layer。
  1 [email protected]:/study# cat d1ed0d8ec4ec460641430566e9a8cece698e60d4ad4afcf48759ad157d340064/json | jq .
26 解釋:主要關於映象的配置資訊,簡要部分資訊如上。
  1 [email protected]:/study# tar -tf d1ed0d8ec4ec460641430566e9a8cece698e60d4ad4afcf48759ad157d340064/layer.tar
27 解釋:包括一個類 Linux 檔案目錄的結構,儲存著這個 layer 所做的修改。

四 Dockerfile、Docker映象和Docker容器

4.1 關係

Dockerfile 是軟體的原材料,Docker 映象是軟體的交付品,而 Docker 容器則可以認為是軟體的執行態。從應用軟體的角度來看,Dockerfile、Docker 映象與 Docker 容器分別代表軟體的三個不同階段,Dockerfile 面向開發,Docker 映象成為交付標準,Docker 容器則涉及部署與運維。 28 Dockerfile構建出Docker映象,通過Docker映象執行Docker容器。 29 參考連結: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。結構如下圖所示: 30

5.3 OverlayFS

Overlay是Linux核心3.18後支援的,也是一種Union FS,和AUFS的多層不同的是Overlay只有兩層:一個upper檔案系統和一個lower檔案系統,分別代表Docker的映象層和容器層。當需要修改一個檔案時,使用CoW將檔案從只讀的lower複製到可寫的upper進行修改,結果也儲存在upper層。在Docker中,底下的只讀層就是image,可寫層就是Container。 31

5.4 Device mapper

Device mapper是Linux核心2.6.9後支援的,提供的一種從邏輯裝置到物理裝置的對映框架機制,在該機制下,使用者可根據需要制定實現儲存資源的管理策略。 不同於AUFS和OverlayFS的檔案級儲存,Device mapper是塊級儲存,所有的操作都是直接對塊進行操作,而不是檔案。 Device mapper驅動會先在塊裝置上建立一個資源池,然後在資源池上建立一個帶有檔案系統的基本裝置,所有映象都是這個基本裝置的快照,而容器則是映象的快照。 所以在容器裡看到檔案系統是資源池上基本裝置的檔案系統的快照,並不有為容器分配空間。當要寫入一個新檔案時,在容器的映象內為其分配新的塊並寫入資料,即用時分配。當要修改已有檔案時,再使用CoW為容器快照分配塊空間,將要修改的資料複製到在容器快照中新的塊裡再進行修改。 Device mapper 驅動預設會建立一個100G的檔案包含映象和容器。每一個容器被限制在10G大小的卷內,大小可配置調整。 32

5.5 Btrfs

Btrfs被稱為下一代寫時複製檔案系統,併入Linux核心,也是檔案級級儲存,但可以像Device mapper直接操作底層裝置。 Btrfs把檔案系統的一部分配置為一個完整的子檔案系統,稱之為subvolume 。那麼採用 subvolume,一個大的檔案系統可以被劃分為多個子檔案系統,這些子檔案系統共享底層的裝置空間,在需要磁碟空間時便從底層裝置中分配。 為了靈活利用裝置空間,Btrfs 將磁碟空間劃分為多個chunk 。每個chunk可以使用不同的磁碟空間分配策略。比如某些chunk只存放metadata,某些chunk只存放資料。這種模型有很多優點,比如Btrfs支援動態新增裝置。 使用者在系統中增加新的磁碟之後,可以使用Btrfs的命令將該裝置新增到檔案系統中。 Btrfs把一個大的檔案系統當成一個資源池,配置成多個完整的子檔案系統,還可以往資源池裡加新的子檔案系統,而基礎映象則是子檔案系統的快照,每個子映象和容器都有自己的快照,這些快照則都是subvolume的快照。 當寫入一個新檔案時,為在容器的快照裡為其分配一個新的資料塊,檔案寫在這個空間裡,這個叫用時分配。而當要修改已有檔案時,使用CoW複製分配一個新的原始資料和快照,在這個新分配的空間變更資料,變結束再更新相關的資料結構指向新子檔案系統和快照,原來的原始資料和快照沒有指標指向,被覆蓋。 33

5.6 ZFS

ZFS 檔案系統是一個革命性的全新的檔案系統,它從根本上改變了檔案系統的管理方式,ZFS 完全拋棄了“卷管理”,不再建立虛擬的卷,而是把所有裝置集中到一個儲存池中來進行管理,用“儲存池”的概念來管理物理儲存空間。過去,檔案系統都是構建在物理裝置之上的。為了管理這些物理裝置,併為資料提供冗餘,“卷管理”的概念提供了一個單裝置的映像。而ZFS建立在虛擬的,被稱為“zpools”的儲存池之上。每個儲存池由若干虛擬裝置(virtual devices,vdevs)組成。這些虛擬裝置可以是原始磁碟,也可能是一個RAID1映象裝置,或是非標準RAID等級的多磁碟組。於是zpool上的檔案系統可以使用這些虛擬裝置的總儲存容量。 34 Docker裡ZFS的使用。首先從zpool裡分配一個ZFS檔案系統給映象的基礎層,而其他映象層則是這個ZFS檔案系統快照的克隆,快照是隻讀的,而克隆是可寫的,當容器啟動時則在映象的最頂層生成一個可寫層。如下圖所示: 35 當要寫一個新檔案時,使用按需分配,一個新的資料快從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 [email protected]:~# vi /etc/docker/daemon.json
  2 {
  3 "storage-driver": "overlay2"
  4 }

六 建立映象

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

6.1 更新映象並提交

  1. 執行容器
  2. 修改容器
  3. 將容器儲存為新的映象
  1 [email protected]:~# docker run --name centos-7-01 -it centos:7 /bin/bash	#建立容器
  2 [[email protected] /]# yum -y install net-tools vim openssh-clients wget ntp bash-completion    #安裝軟體
  3 [[email protected] /]# exit
  4 [email protected]:~# docker commit -m="has modify" -a="xhy" 01b2b251e216 centos-7-01
  5 [email protected]:~# docker images
36 引數說明:
  • -m:提交的描述資訊
  • -a:指定映象作者
  • 01b2b251e216 :容器ID
  • centos-7-01:指定要建立的目標映象名
  1 [email protected]:~# docker images						#檢視映象
更新現有映象缺陷
  • 手動建立,容易出錯,效率低及可重複性弱
  • 使用者並不知道映象是如何創建出來的,裡面是否有惡意程式,可能存在案例隱患

6.2 Dockerfile構建映象舉例

  1 [email protected]:~# mkdir /dockerfiles
  2 [email protected]:~# cd /dockerfiles/
  3 [email protected]:/dockerfiles# vi Dockerfile
  4 FROM            centos:7
  5 MAINTAINER  Fisher "[email protected]"
  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 [email protected]:/dockerfiles# docker build -t xhy/centos7 /dockerfiles/
引數說明:
  • -t :指定要建立的目標映象名
  • /dockerfiles/:Dockerfile 檔案所在目錄
  1 [email protected]:~# docker images						#檢視映象
37
  1 [email protected]:/dockerfiles# docker run -t -i xhy/centos7  /bin/bash	#建立容器
38

七 Dockerfile詳解

7.1 Dockerfile典型結構

  1 From ubutu						#第一行必須指令基於的基礎映象
  2 MAINTAINER docker_user  [email protected]        #維護者資訊
  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 中非註釋行的第一個指令,即一個 Dockerf