Docker(四)--存儲卷

在談及存儲卷之前,我們先來看看docker鏡像與容器之間的關係。

1.什麼是docker鏡像

Docker 鏡像是一個只讀的 Docker 容器模板,含有啓動 Docker 容器所需的文件系統結構及其內容,因此是啓動一個 Docker 容器的基礎。
在這裏插入圖片描述
採用分層構建機制,最底層爲 bootfs,其之上 rootfs。

bootfs: 用於系統引導的文件系統,包括 bootloader 和 kernel,容器啓動完成後會被卸載以節約內存資源。
rootfs: 位於 bootfs 之上,rootfs 是 Docker 容器在啓動時內部進程可見的文件系統,即 Docker 容器的根目錄。rootfs 通常包含一個操作系統運行所需的文件系統,例如可能包含典型的類Unix操作系統中的目錄系統,如/dev、/proc、/bin、/etc、/lib、/usr、/tmp及運行 Docker 容器所需的配置文件、工具等

在傳統的 Linux 操作系統內核啓動時,首先掛載一個只讀(read-only)的rootfs,當系統檢測其完整性之後,再將其切換爲讀寫(read-write)模式;而在Docker架構中,當 Docker daemon 爲 Docker 容器掛載 rootfs 時,沿用了 Linux 內核啓動時的方法,即將 rootfs 設爲只讀模式。在掛載完畢之後,利用聯合掛載(union mount)技術在已有的只讀 rootfs 上再掛載一個讀寫層。這樣,可讀寫層處於 Docker 容器文件系統的最頂層,其下可能聯合掛載多個只讀層,只有在 Docker 容器運行過程中文件系統發生變化時,纔會把變化的文件內容寫到可讀寫層,並隱藏只讀層中的老版本文件。如下圖:
在這裏插入圖片描述

Docker鏡像的主要特點:

  • 分層: Docker 鏡像時採用分層的方式構建的,每個鏡像都由一系列的"鏡像層"組成。分層結構是Docker鏡像如此輕量的重要原因,當需要修改容器鏡像內的某個文件時,只對處於最上方的讀寫層進行變動,不覆寫下層已有文件系統的內容,已有文件在只讀層中的原始版本仍然存在,但會被讀寫層中的新版本文件所隱藏。當使用 docker commit 提交這個修改過的容器文件系統爲一個新的鏡像時,保存的內容僅爲最上層讀寫文件系統中被更新過的文件。分層達到了在不同鏡像之間共享鏡像層的效果。
  • 寫時複製: Docker 鏡像使用了寫時複製(copy-on-write)策略,在多個容器之間共享鏡像,每個容器在啓動的時候並不需要單獨複製一份鏡像文件,而是將所有鏡像層以只讀的方式掛載到一個掛載點,再在上面覆蓋一個可讀寫的容器層。在未更改文件內容時,所有容器都共享一份數據,只有在 Docker 容器運行過程中文件系統發生變化時,纔會把變化的文件拷貝到可讀寫層進行修改,並隱藏只讀層中的老版本文件。寫時複製配合分層機制減少了鏡像對磁盤空間的佔用和容器啓動時間。
  • 內容尋址: 在Docker 1.10版本後,Docker鏡像改動較大,其中最重要的特性便是引入了內容尋址存儲(content-addressable storge)的機制,根據文件內容來索引鏡像的鏡像層。與之前版本對每一個鏡像層隨機生成一個UUID不同,新模型對鏡像層的內容計算校驗和,生成一個內容哈希值,並以此哈希值代替之前的UUID作爲鏡像層的唯一標誌。該機制主要提高了鏡像的安全性,並在pull、push、load、save操作後檢測數據的完整性。另外,基於內容哈希來索引鏡像層,在一定程度上減少了ID的衝突並且增強了鏡像層的共享。對於來自不同構建的鏡像層,只要擁有相同的內容哈希,也能被不同的鏡像共享。
  • 聯合掛載: 通俗的講,聯合掛載技術可以在一個掛載點同時掛載多個文件系統,將掛載點的原目錄與被掛載內容進行整合,使得最終可見的文件系統將會包含整合之後的各層的文件和目錄。實現這種聯合掛載技術的文件系統通常被稱爲聯合文件系統(Union FileSystem)。

就我的理解來說,容器就相當於鏡像加上可寫層,與是否運行無關。

2.存儲卷

從上我們可以知道,Docker鏡像由多個只讀層疊加而成,啓動容器時,Docker會加載只讀鏡像層並在鏡像棧頂部添加一個讀寫層,如果運行中的容器修改了現有的一個已經存在的文件,那該文件將會從讀寫層下面的只讀層複製到讀寫層,該文件的只讀版本仍然存在,只是已經被讀寫層中該文件的副本所隱藏,此即"寫時複製(COW)"機制。
在這裏插入圖片描述
現在我們知道,一個運行的容器有一個或多個只讀層和一個讀寫層。在容器運行過程中,若產生了一些重要的數據或是更改了一些文件,這些更改我們應該怎麼保存呢?容器關閉或重啓,這些數據不受影響;但刪除Docker容器,則數據將會全部丟失。除此之外也還有其他的一些問題。

存在的問題:

  • 存儲於聯合文件系統中,不易於宿主機訪問
  • 容器間數據共享不便

爲了解決這些問題,Docker引入了數據卷(volume)機制。volume是存在於一個或多個容器中的特定文件或文件夾,這個目錄以獨立於聯合文件系統的形式在宿主機中存在,併爲數據的共享與持久化提供以下便利。

  • volume在容器創建時就會初始化,在容器運行時就可以使用其中的文件。
  • volume能在不同的容器之間共享和重用。
  • 對volume中數據的操作會馬上生效。
  • 對volume中數據的操作不會影響到鏡像本身
  • volume的生存週期獨立於容器的生存週期,即使刪除容器,volume仍然會存在,沒有任何容器使用的volume也不會被Docker刪除。

卷的分類:

1. Docker-managed volume
Docker 自身管理數據卷,容器中的文件目錄由用戶指定,宿主機隨機生成掛載目錄

~]# docker container run --name bbox -it -v /data busybox:latest		#會在容器創建時創建/data目錄

~]# docker container inspect -f {{.Mounts}} bbox
[{... /var/lib/docker/volumes/f2a6ba52d5e1666ab4b5809579c013b821abd3403c9a6f9d80fb76323e88bffc/_data /data local  true }]

可見宿主機的 /var/lib/docker/volumes/f2a6ba52d5e1666ab4b5809579c013b821abd3403c9a6f9d80fb76323e88bffc/_data 目錄與容器中的 /data 目錄進行了掛載,此時容器中寫在 /data 目錄下的數據,宿主機都可在對應目錄下查看,且持久保存。

注:若在啓動容器時,使用了 --rm 選項,則當容器停止時,宿主機掛載的相應目錄也會被刪除,請謹慎使用!

2. Bind mount volume
綁定掛載目錄,用戶在啓動容器時指定容器中的目錄與宿主機中目錄進行綁定

~]# docker container run --name bbox -it --rm -v /docker/data:/data busybox:latest

~]# docker container inspect -f {{.Mounts}} bbox
[{bind  /docker/data /data   true rprivate}]

存儲卷操作

1. 共享數據卷:
多個容器的卷使用同一個主機目錄,例如

~]# docker container run –it --name c1 -v /docker/volumes/v1:/data busybox
~]# docker container run –it --name c2 -v /docker/volumes/v1:/data busybox

2. 引用數據卷:
複製使用其它容器的卷,爲docker run命令使用–volumes-from選項

~]# docker container run -it --name bbox1 -v /docker/volumes/v1:/data busybox
~]# docker container run -it --name bbox2 --volumes-from bbox1 busybox

3. 刪除數據卷:
在刪除容器之時刪除相關的卷

~]# docker container run --rm -v ...

刪除指定的卷,volume name 可查看容器信息中的 Mounts.Name字段查看,但需要注意的是當容器還存在(不論是否運行),刪除存儲卷將不成功

~]# docker volume rm VOLUME_NAME...

注:掛載卷的目錄不需要手動創建,運行容器時會自動生成。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章