Docker鏡像原理之聯合文件系統和分層理解(實例詳解)

本篇文章給大家帶來了關于docker鏡像原理之聯合文件系統和分層理解的相關知識,其中包括聯合文件系統、分層結構和分層實踐的相關問題,希望對大家有幫助。

Docker鏡像原理之聯合文件系統和分層理解(實例詳解)

docker——鏡像原理之聯合文件系統和分層理解

1、聯合文件系統

UnionFS( 聯合文件系統)

UnionFS( 聯合文件系統):Union文件系統(UnionFS )是一種分層、輕量級并且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtualfilesystem)。Union文件系統是Docker鏡像的基礎。鏡像可以通過分層來進行繼承,基于基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像。

另外,不同 Docker 容器就可以共享一些基礎的文件系統層,同時再加上自己獨有的改動層,大大提高了存儲的效率。

Docker 中使用的 AUFS(AnotherUnionFS)就是一種聯合文件系統。 AUFS 支持為每一個成員目錄(類似 Git 的分支)設定只讀(readonly)、讀寫(readwrite)和寫出(whiteout-able)權限, 同時 AUFS 里有一個類似分層的概念, 對只讀權限的分支可以邏輯上進行增量地修改(不影響只讀部分的)。

Docker 目前支持的聯合文件系統種類包括 AUFS, btrfs, vfs 和 DeviceMapper。

特性:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄。

base 鏡像

base 鏡像簡單來說就是不依賴其他任何鏡像,完全從0開始建起,其他鏡像都是建立在他的之上,可以比喻為大樓的地基,docker鏡像的鼻祖。

base 鏡像有兩層含義:(1)不依賴其他鏡像,從 scratch 構建;(2)其他鏡像可以之為基礎進行擴展。

所以,能稱作 base 鏡像的通常都是各種 Linux 發行版的 Docker 鏡像,比如 Ubuntu, Debian, CentOS 等。

Docker 鏡像加載原理

docker的鏡像實際上由一層一層的文件系統組成,這種層級的文件系統就是UnionFS。

典型的 Linux 啟動到運行需要兩個FS,bootfs + rootfs:

Docker鏡像原理之聯合文件系統和分層理解(實例詳解)

bootfs(boot file system)主要包含 bpotloader 和 kernel,bootloader主要是引導加載 kernel,Linux 剛啟動時會加載 bootfs文件系統,在Docker鏡像的最底層是bootfs。這一層與我們典型的Linux/Unix系統是一樣的,包含boot加載器bootloader和內核kernel。當boot加載完成之后整個內核就都在內存中了,此時內存的使用權已由bootfs轉交給內核,此時系統也會卸載bootfs。

rootfs (root file system),在bootfs之上。包含的就是典型Linux系統中的/dev, /proc, /bin, /etc等標準目錄和文件。roots就是各種不同的操作系統發行版,比如Ubuntu,Centos等等。

Docker 鏡像中為什么沒有內核

從鏡像大小上面來說,一個比較小的鏡像只有1KB多點,或幾MB,而內核文件需要幾十MB, 因此鏡像里面是沒有內核的,鏡像在被啟動為容器后將直接使用宿主機的內核,而鏡像本身則只提供相應的rootfs,即系統正常運行所必須的用戶空間的文件系統,比如/dev/,/proc,/bin,/etc等目錄,所以容器當中基本是沒有/boot目錄的,而/boot當中保存的就是與內核相關的文件和目錄。

由于容器啟動和運行過程中是直接使用了宿主機的內核,不會直接調用過物理硬件,所以也不會涉及到硬件驅動,因此也用不上內核和驅動。而如果虛擬機技術,對應每個虛擬機都有自已獨立的內核

2、分層結構

Docker 鏡像是一種分層結構,每一層構建在其他層之上,從而實現增量增加內容的功能,Docker 鏡像下載的時候也是分層下載,以下載redis鏡像為例:

Docker鏡像原理之聯合文件系統和分層理解(實例詳解)

Docker鏡像原理之聯合文件系統和分層理解(實例詳解)

可以看到,新鏡像是從 base 鏡像一層一層疊加生成的。每安裝一個軟件,就在現有鏡像的基礎上增加一層。

為什么 Docker 鏡像要采用這種分層結構呢?

最大的好處,莫過于是資源共享了。比如有多個鏡像都從相同的Base鏡像構建而來,那么宿主機只需在磁盤上保留一份base鏡像,同時內存中也只需要加載一份base鏡像,這樣就可以為所有的容器服務了,而且鏡像的每一層都可以被共享。

可寫的容器層

Docker 鏡像都只是可讀(read-only)的,當容器啟動時,一個新的可寫層被加載到鏡像頂部。

這新的一層就是可寫的容器層,容器之下都叫鏡像層。

Docker鏡像原理之聯合文件系統和分層理解(實例詳解)

Docker通過一個修改時復制策略copy-on-write來保證base鏡像的安全性,以及更高的性能和空間利用率。

  • 當容器需要讀取文件的時候

從最上層的鏡像層開始往下找,找到后讀取到內存中,若已經在內存中,可以直接使用。換句話說,運行在同一臺機器上的Docker容器共享運行時相同的文件。

  • 當容器需要修改文件的時候

從上往下查找,找到后復制到容器層,對于容器來說,可以看到的是容器層的這個文件,看不到鏡像層里的文件,然后直接修改容器層的文件。

  • 當容器需要刪除文件的時候

從上往下查找,找到后在容器中記錄刪除,并不是真正的刪除,而是軟刪除。這導致鏡像體積只會增加,不會減少。

  • 當容器需要增加文件的時候

直接在最上層的容器可寫層增加,不會影響鏡像層。

所有對容器的改動,無論添加、刪除、還是修改文件都只會發生在容器層中。只有容器層是可寫的,容器層下面的所有鏡像層都是只讀的,所以鏡像可以被多個容器共享。

3、分層實踐——commit 提交鏡像

通過鏡像創建容器,然后對容器層進行操作,鏡像層不動,再把操作后的容器層和鏡像層打包成一個新的鏡像提交。

docker commit:用容器創建一個新的鏡像。

語法:

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

OPTIONS說明:

  • **-a*提交的鏡像作者;
  • **-c*使用Dockerfile指令來創建鏡像;
  • **-m *提交時的說明文字;
  • **-p *在commit時,將容器暫停。

使用實例:通過鏡像創建容器,然后對容器層進行操作,再把操作后的容器層和鏡像層打包成一個新的鏡像提交。

1、先下載 tomcat 鏡像

2、通過tomcat 鏡像創建運行tomcat 容器:

docker run -d --name="tomcat01" tomcat

3、進入正在運行的tomcat容器:

docker exec -it tomcat01 /bin/bash

4、把tomcat容器 webapps.dist目錄下的文件拷貝到webapps目錄下:

cp -r webapps.dist/* webapps

5、docker commit 提交鏡像

將容器 dc904437d987 保存為新的鏡像,并添加提交人信息和說明信息,提交后的鏡像名為tomcatplus,版本為1.0:

docker commit -a="wanli" -m="add webapps files" dc904437d987 tomcatplus:1.0

Docker鏡像原理之聯合文件系統和分層理解(實例詳解)

可以看到commit提交后的新 tomcat 鏡像大小比原來的tomcat鏡像要大一點,因為我們在容器層中進行了復制文件操作。

Docker鏡像原理之聯合文件系統和分層理解(實例詳解)

推薦學習:《docker視頻教程

? 版權聲明
THE END
喜歡就支持一下吧
點贊6 分享