15、《每天5分鐘玩轉Docker容器技術》學習--Single-host存儲

------------------------------------重要說明------------------------------------

本文內容都是參考Cloudman系列進行學習,是個人學習過程記錄,與原版不同!

原版請參考cloudman《每天5分鐘玩轉Docker容器技術》Cloudman博客如下:

https://blog.51cto.com/cloudman

------------------------------------重要說明------------------------------------

Docker 爲容器提供了兩種存放數據的資源:

1.storage driver 管理的鏡像層和容器層。

2.Data Volume

3.storage driver 和 data volume 是容器存放數據的兩種方式

1. storage driver

圖片.png

容器由最上面一個可寫的容器層,以及若干只讀的鏡像層組成,容器的數據就存放在這些層中。這樣的分層結構最大的特性是 Copy-on-Write:

1.新數據會直接存放在最上面的容器層

2.修改現有數據會先從鏡像層將數據複製到容器層,修改後的數據直接保存在容器層中,鏡像層保持不變。

3.如果多個層中有命名相同的文件,用戶只能看到最上面那層中的文件。

分層結構使鏡像和容器的創建、共享以及分發變得非常高效,而這些都要歸功於 Docker storage driver。正是 storage driver 實現了多層數據的堆疊併爲用戶提供一個單一的合併之後的統一視圖。

Docker 支持多種 storage driver,有 AUFS、Device Mapper、Btrfs、OverlayFS、VFS 和 ZFS。它們都能實現分層的架構,同時又有各自的特性。對於 Docker 用戶來說,具體選擇使用哪個 storage driver 是一個難題,因爲:

1.沒有哪個 driver 能夠適應所有的場景。

2.driver 本身在快速發展和迭代。

不過 Docker 官方給出了一個簡單的答案:優先使用 Linux 發行版默認的 storage driver

Docker 安裝時會根據當前系統的配置選擇默認的 driver。默認 driver 具有最好的穩定性,因爲默認 driver 在發行版上經過了嚴格的測試。

運行docker info查看 Ubuntu 的默認 driver,下圖只截取了部分信息:

圖片.png

Ubuntu 用的 AUFS,底層文件系統是 xfs,各層數據存放在 /var/lib/docker/aufs。

Redhat/CentOS 的默認 driver 是 Device Mapper,SUSE 則是 Btrfs。

對於某些容器,直接將數據放在由 storage driver 維護的層中是很好的選擇,比如那些無狀態的應用。無狀態意味着容器沒有需要持久化的數據,隨時可以從鏡像直接創建。

比如 busybox,它是一個工具箱,我們啓動 busybox 是爲了執行諸如 wget,ping 之類的命令,不需要保存數據供以後使用,使用完直接退出,容器刪除時存放在容器層中的工作數據也一起被刪除,這沒問題,下次再啓動新容器即可。

但對於另一類應用這種方式就不合適了,它們有持久化數據的需求,容器啓動時需要加載已有的數據,容器銷燬時希望保留產生的新數據,也就是說,這類容器是有狀態的。

這就要用到 Docker 的另一種存儲機制:Data Volume

2. Data Volume

Data Volume 本質上是 Docker Host 文件系統中的目錄或文件,能夠直接被 mount 到容器的文件系統中。Data Volume 有以下特點:

1.Data Volume 是目錄或文件,而非沒有格式化的磁盤(塊設備)。

2.容器可以讀寫 volume 中的數據。

3.volume 數據可以被永久的保存,即使使用它的容器已經銷燬。

好,現在我們有數據層(鏡像層和容器層)和 volume 都可以用來存放數據,具體使用的時候要怎樣選擇呢?考慮下面幾個場景:

1.Database 軟件 vs Database 數據

2.Web 應用 vs 應用產生的日誌

3.數據分析軟件 vs input/output 數據

4.Apache Server vs 靜態 HTML 文件

相信大家會做出這樣的選擇:

1.前者放在數據層中。因爲這部分內容是無狀態的,應該作爲鏡像的一部分。

2.後者放在 Data Volume 中。這是需要持久化的數據,並且應該與鏡像分開存放

還有個大家可能會關心的問題:如何設置 voluem 的容量?

因爲 volume 實際上是 docker host 文件系統的一部分,所以 volume 的容量取決於文件系統當前未使用的空間,目前還沒有方法設置 volume 的容量。

docker 提供了兩種類型的 volume:bind mount 和 docker managed volume

a) Bind mount

bind mount 是將 host 上已存在的目錄或文件 mount 到容器。

例如 docker host 上有目錄 $HOME/htdocs/index.html:

圖片.png

通過 -v 將其 mount 到 httpd 容器:

圖片.png

-v 的格式爲 <host path>:<container path>。/usr/local/apache2/htdocs 就是 apache server 存放靜態文件的地方。由於 /usr/local/apache2/htdocs 已經存在,原有數據會被隱藏起來,取而代之的是 host $HOME/htdocs/ 中的數據,這與 linux mount 命令的行爲是一致的。

圖片.png

圖片.png
 


 

圖片.png

可以看到本地的/root/htdocs/目錄中的信息映射到了container目錄當中;

b) Bind數據持久性

1) 在容器中添加內容

進入容器當中進行對/usr/local/apache2/htdocs/當中添加信息,例如創建文件或目錄,是否會在host主機端存在?

答案:可以的,當把容器停止/刪除也會永久存儲

圖片.png

 

2) 在host主機中添加內容

圖片.png

圖片.png 

圖片.png 

圖片.png 

創建文件

圖片.png

進入容器查看

圖片.png 

圖片.png
 

 

3) 容器銷燬看看對數據有什麼影響

圖片.png 

圖片.png
 圖片.png

可見,即使容器沒有了,bind mount 也還在。這也合理,bind mount 是 host 文件系統中的數據,只是借給容器用用,哪能隨便就刪了啊。

 

4) 對映射文件的讀寫(默認可讀可寫)

另外,bind mount 時還可以指定數據的讀寫權限,默認是可讀可寫,可指定爲只讀:

圖片.png

圖片.png 

圖片.png 

1.對container文件進行讀測試

圖片.png 

可以發現讀,沒有問題

2.對container文件進行寫測試

圖片.png 

可以發現寫操作也沒有問題

3.對host中的文件寫,對container中文件產生什麼效果?

host端進行數據追加

圖片.png
 

Container端進行信息查看

圖片.png
 

可以發現host端更改之後主機端信息也發生了改變。

5) 把相同目錄掛載給多個container

新建container【test_volume_bind_RO】並掛載/root/docker_file/,並且進行寫入操作

圖片.png

在container【test_volume_bind】中查看信息

圖片.png
 

由此可見通過Bind方式可以將相同的信息掛載多個container中。

 

 

6) 以只讀方式掛載

docker run -it --name test_volume_bind_readonly -v /root/docker_file/:/root/docker_file/:ro centos

圖片.png

圖片.png 

圖片.png 

通過上圖結果可以看出來,無法進行寫入操作。

 

c) Bind mount小結

使用單一文件有一點要注意:host 中的源文件必須要存在,不然會當作一個新目錄 bind mount 給容器。

mount point 有很多應用場景,比如我們可以將源代碼目錄 mount 到容器中,在 host 中修改代碼就能看到應用的實時效果。再比如將 mysql 容器的數據放在 bind mount 裏,這樣 host 可以方便地備份和遷移數據

bind mount 的使用直觀高效,易於理解,但它也有不足的地方:bind mount 需要指定 host 文件系統的特定路徑,這就限制了容器的可移植性,當需要將容器遷移到其他 host,而該 host 沒有要 mount 的數據或者數據不在相同的路徑時,操作會失敗。

d) docker managed volume

1) Docker manager volume基本用法

docker managed volume 與 bind mount 在使用上的最大區別是不需要指定 mount 源,指明 mount point 就行了。

圖片.png

當-d和-it參數同時使用時就不會exited

通過 -v 告訴 docker 需要一個 docker manager volume,並將其 mount 到 /root/docker_file/

進入container查看是否掛載成功

圖片.png
 

可以看到container中有/root/docker_file目錄,說明掛載是沒有問題的;那另一個問題來了,掛載的docker manager volume是哪裏來的呢?

通過docker inspect命令進行對container【test_data_volume】查看

圖片.png

其中有很多信息,我們查看Mounts部分

圖片.png 

Source項就是我們的docker manager volume的地址

"Source": "/var/lib/docker/volumes/c2f90b8dfb7cd756f7b733fcf448911d08588a87eea52d24084a0674dfe4281f/_data",

可見docker會在/var/lib/docker/volumes/目錄下生成,那之後的c2f90b8dfb7cd756f7b733fcf448911d08588a87eea52d24084a0674dfe4281f/_data目錄又是什麼意思呢?在container中創建文件進行測試

圖片.png 

圖片.png
 

在host中目錄查看

圖片.png 

可以看到數據實際是放到了/var/lib/docker/volumes/c2f90b8dfb7cd756f7b733fcf448911d08588a87eea52d24084a0674dfe4281f/_data的目錄中的

/var/lib/docker/volumes這個目錄是docker所有docker manager volume存放目錄

c2f90b8dfb7cd756f7b733fcf448911d08588a87eea52d24084a0674dfe4281f是container的docker manager volume

_data是 docker manager volume創建的,最終給container存放數據

再通過一個實驗進一步瞭解docker manager volume

2) Docker manager volume高級用法

上個實驗中是將docker manager volume掛載到了container中的空目錄中,那如果掛載到非空目錄中是什麼情況?

圖片.png

圖片.png 

Container創建成功,說明掛載沒有問題。

進入容器查看/etc/sysconfig/目錄下內容

圖片.png
 

可以看到/etc/sysconfig/目錄下有內容

在host中查看信息

通過docker inspect查看容器使用的是哪個docker manager volume

docker inspect test_data_volume01

圖片.png

5fbfbccdae98095f420ba2d62607e42a0d08a211f4004c236159da214129f74b

圖片.png

可以發現container中的目錄下的內容映射到了主機中

注意:當使用docker manager volume映射給container中的目錄,目錄中有信息,那麼會把當前目錄中的信息複製到docker manager volume

e) Bing mount與docker manager volume對比

圖片.png

f) 數據共享

1) Host與constainer共享數據

兩種類型的 data volume,它們均可實現在容器與 host 之間共享數據,但方式有所區別。

對於 bind mount 是非常明確的:直接將要共享的目錄 mount 到容器。具體請參考前面 httpd 的例子,不再贅述。

docker managed volume 就要麻煩點。由於 volume 位於 host 中的目錄,是在容器啓動時才生成,所以需要將共享數據拷貝到 volume 中。請看下面的例子:

圖片.png

圖片.png 

圖片.png 

當前container中沒有/root/docker_file/目錄,所以無法複製

在container中建立相應的目錄

圖片.png

圖片.png

在host中繼續進行復制

圖片.png
 

在container中查看

圖片.png
 

docker cp 可以在容器和 host 之間拷貝數據,當然我們也可以直接通過 Linux 的 cp 命令複製到 /var/lib/docker/volumes/xxx。

2) 容器之間共享數據-Bind mount

新建container【test_volume_bind_RO】並掛載/root/docker_file/,並且進行寫入操作

圖片.png

在container【test_volume_bind】中查看信息

圖片.png

由此可見通過Bind方式可以將相同的信息掛載多個container中。

3) 容器之間共享數據-volume container

volume container 是專門爲其他容器提供 volume 的容器。它提供的卷可以是 bind mount,也可以是 docker managed volume。下面我們創建一個 volume container:

圖片.png

我們將容器命名爲 VC_data(VC 是 volume container 的縮寫)。注意這裏執行的是 docker create 命令,這是因爲 volume container 的作用只是提供數據,它本身不需要處於運行狀態。容器 mount 了兩個 volume:

1.bind mount,存放 web server 的靜態文件。

2.docker managed volume,存放一些實用工具(當然現在是空的,這裏只是做個示例)。

通過 docker inspect 可以查看到這兩個 volume。

圖片.png 

其他容器可以通過 --volumes-from 使用 VC_data 這個 volume container:

圖片.png

三個 httpd 容器都使用了 vc_data,看看它們現在都有哪些 volume,以 web01 爲例:

docker inspect web01

圖片.png 

進入容器驗證bind mount與manger volume是否掛載成功

圖片.png
 

Web01 容器使用的就是 vc_data 的 volume,而且連 mount point 都是一樣的。驗證一下數據共享的效果:

Host操作

圖片.png 

圖片.png 

圖片.png 

圖片.png
 

Container【web01】驗證

圖片.png 

Container【web02】驗證

圖片.png
 

Container【web03】驗證

圖片.png
 

Host驗證

圖片.png 

圖片.png 

可見,三個容器已經成功共享了 volume container 中的 volume。

 

總結:

1.與 bind mount 相比,不必爲每一個容器指定 host path,所有 path 都在 volume container 中定義好了,容器只需與 volume container 關聯,實現了容器與 host 的解耦。

2.使用 volume container 的容器其 mount point 是一致的,有利於配置的規範和標準化,但也帶來一定的侷限,使用時需要綜合考慮。

4) 容器之間共享數據-data-packed volume container

在上一節的例子中 volume container 的數據歸根到底還是在 host 裏,有沒有辦法將數據完全放到 volume container 中,同時又能與其他容器共享呢?

當然可以,通常我們稱這種容器爲 data-packed volume container。其原理是將數據打包到鏡像中,然後通過 docker managed volume 共享。

用下面的 Dockfile 構建鏡像:

圖片.png 

圖片.png 

圖片.png 

圖片.png 

圖片.png 

圖片.png 

ADD 將靜態文件添加到容器目錄 /usr/local/apache2/htdocs。
VOLUME 的作用與 -v 等效,用來創建 docker managed volume,mount point 爲 /usr/local/apache2/htdocs,因爲這個目錄就是 ADD 添加的目錄,所以會將已有數據拷貝到 volume 中。 

build 新鏡像 datapacked:

圖片.png 

圖片.png 

圖片.png
 

運行另一個容器進行驗證

圖片.png
 

圖片.png
 

圖片.png
 

容器能夠正確讀取 volume 中的數據。data-packed volume container 是自包含的,不依賴 host 提供數據,具有很強的移植性,非常適合 只使用 靜態數據的場景,比如應用的配置信息、web server 的靜態文件等。

------------------------------------重要說明------------------------------------

本文內容都是參考Cloudman系列進行學習,是個人學習過程記錄,與原版不同!

原版請參考cloudman《每天5分鐘玩轉Docker容器技術》Cloudman博客如下:

https://blog.51cto.com/cloudman

------------------------------------重要說明------------------------------------

書籍:

1.《每天5分鐘玩轉Kubernetes》
https://item.jd.com/26225745440.html

2.《每天5分鐘玩轉Docker容器技術》
https://item.jd.com/16936307278.html

3.《每天5分鐘玩轉OpenStack》
https://item.jd.com/12086376.html



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