Docker 對 container 的使用基本是創建在 LXC 基礎之上,然而 LXC 存在的問題是難以移動,難以經過標準化的模板去製做、重建、複製和移動 container。linux
在以 VM 爲基礎的虛擬化中,有 image 和 snapshot 能夠用於 VM 的複製、重建以及移動的功能。git
想要經過 container 來實現快速的大規模部署和更新,這些功能不可或缺。github
在 Docker 0.7 中引入了 Storage Driver(儲存驅動), 如今已經支持 AUFS、Btrfs、Device Mapper、OverlayFS、ZFS、VFS。web
1、儲存驅動
https://docs.docker.com/storage/storagedriver/select-storage-driver/docker
1.Union FileSystem
簡稱 Union FS(聯合文件系統),儲存驅動的一種。緩存
一種分層、輕量級而且高性能的文件系統,它支持對文件系統的修改做爲一次提交來一層層的疊加,同時能夠將不一樣目錄掛載到同一個虛擬文件系統下。tomcat
特性:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含全部底層的文件和目錄。bash
2.Overlay2
Overlay2 是一種 Union FS,支持爲每個成員目錄(AKA branch)設定 readonly、readwrite 和 whiteout-able 權限。網絡
一般 Union FS 有兩個用途:app
- 不借助 LVM, RAID 將多個 disk 和掛載到一個目錄下。
- 將一個 readonly 的 branch 和一個 writeable 的 branch 聯合在一塊兒,Live CD 正是基於此,能夠容許在 OS image 不變的基礎上容許用戶在其上進行一些寫操做。
Docker 在 Overlay2 上構建的 container image 也正是如此。
OverlayFS 將單個 Linux 主機上的兩個目錄分層,並將它們顯示爲單個目錄。這些目錄稱爲層,統一過程稱爲聯合安裝。
Overlay2 原生支持多達 128 OverlayFS 層。
下圖顯示了 Docker鏡像 和 Docker容器 的分層方式。圖像層是 lowerdir,容器層是 upperdir。統一視圖經過一個被稱爲 merged 容器掛載點的目錄公開。
2、Linux 系統啓動
典型的 Linux 啓動到運行須要兩個FS - bootfs + rootfs (從功能角度而非文件系統角度)
bootfs(boot file system):
主要包含 bootloader 和 kernel,bootloader 主要是引導加載 kernel,當 kernel 被加載到內存中後,bootfs 就被 umount 了,此時內存的使用權已由 bootfs 轉交給 kernel。
rootfs (root file system) :
在 bootfs 之上。包含的就是典型 Linux 系統中的 /dev、/proc、/bin、/etc 等標準目錄和文件。
因而可知對於不一樣的 linux 發行版,bootfs 基本是一致的,rootfs 會有差異,,所以不一樣的發行版能夠公用 bootfs。以下圖:
3、Docker image 結構
典型的 Linux 在啓動後,首先將 rootfs 置爲 readonly,進行一系列檢查, 而後將其切換爲 "readwrite" 供用戶使用。
在 Docker 中,起初也是將 rootfs 以 readonly 方式加載並檢查,然而接下來利用 union mount 將一個 readwrite 文件系統掛載在 readonly 的 rootfs 之上,而且容許再次將下層的 file system 設定爲 readonly,而且向上疊加。
這樣一組 readonly 和一個 writeable 的結構構成一個 container 的運行目錄,每個被稱做一個 Layer。以下圖:
得益於 AUFS 的特性,每個對 readonly 層文件或目錄的修改都只會存在於上層的 writeable 層中。
這樣,因爲不存在競爭, 多個 container 能夠共享 readonly 的 layer。
因此 docker 將 readonly 的層稱做 image,對於 container 而言整個 rootfs 都是 read-write 的,但事實上全部的修改都寫入最上層的 writeable 層中。
image 不保存用戶狀態,能夠用於模板、重建和複製。
某個鏡像:
基於該鏡像建立的容器:
上層的 image 依賴下層的 image,所以 docker 中把下層的 image 稱做父 image,沒有父 image 的 image 稱做 base image。
所以想要從一個 image 啓動一個 container,docker 會先加載其父 image 直到 base image,用戶的進程運行在 writeable 的 layer 中。
全部 parent image 中的數據信息以及 ID、網絡和 lxc 管理的資源限制等具體 container 的配置,構成一個 docker 概念上的 container。以下圖:
Docker image 採用分層結構的好處
共享資源,節省存儲空間:有多個鏡像都從相同的 base 鏡像構建而來,那麼宿主機只需在磁盤上保存一份 base 鏡像,同時內存中也只需加載一份 base 鏡像,就能夠爲全部容器服務了。並且鏡像的每一層均可以被共享。
快速部署:若是要部署多個 container,base image 能夠避免屢次拷貝。
內存更省:由於多個 container 共享 base image,以及 OS 的 disk 緩存機制,多個 container 中的進程命中緩存內容的概率大大增長。
升級更方便:相比於 copy-on-write 類型的文件系統,base-image 也是能夠掛載爲可 writeable 的,能夠經過更新 base image 而一次性更新其之上的 container。
容許在不更改 base-image 的同時修改其目錄中的文件,全部寫操做都發生在最上層的 writeable 層中。
4、Docker 鏡像 commit
docker commit 提交容器副本使之成爲一個新的鏡像
# docker commit -m=「提交的描述信息」 -a=「做者」 容器ID 要建立的目標鏡像名:[標籤名] # 下載鏡像 docker pull tomcat # 啓動鏡像 docker run -d -p 8080:8080 tomcat # 查看容器ID docker ps -a # 進入容器 docker exec -it a41c393cfa45 /bin/bash # 刪除 tomcat rm -rf /usr/local/tomcat/webapps/* # 退出容器 exit # 生成新鏡像 docker commit -m=「沒有webapps的tomcat鏡像」 -a=「jhxxb」 a41c393cfa45 jhxxb/tomcat-del:1.0 # 查看生成的新鏡像 docker images # 運行新鏡像(須要指定版本,默認爲 latest) docker run -d -p 8080:8080 jhxxb/tomcat-del:1.0
能夠看到新鏡像的 webapps 目錄下沒有文件
http://tiewei.github.io/cloud/Docker-Getting-Start/
https://docs.docker.com/storage/storagedriver/overlayfs-driver/#how-the-overlay2-driver-works