Docker學習-Docker存儲

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

  • 由 storage driver 管理的鏡像層和容器層。
  • Data Volume。

storage driver

docker的鏡像分層結構,如下所示:
Docker學習-Docker存儲
Docker鏡像中引入層layer的概念,鏡像的製作過程中的每一步擦歐總,都會生成一個新的鏡像層

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

  • 新數據會直接存放在最上面的容器層。
  • 修改現有數據會先從鏡像層將數據複製到容器層,修改後的數據直接保存在容器層中,鏡像層保持不變。
  • 如果多個層中有命名相同的文件,用戶只能看到最上面那層中的文件。
    分層結構使鏡像和容器的創建、共享以及分發變得非常高效,而這些都要歸功於 Docker storage driver。正是 storage driver 實現了多層數據的堆疊併爲用戶提供一個單一的合併之後的統一視圖。
    Docker 支持多種 storage driver,有 AUFS、Device Mapper、Btrfs、OverlayFS、VFS 和 ZFS。它們都能實現分層的架構,同時又有各自的特性。
    Docker會優先使用 Linux 發行版默認的 storage driver。
    Docker 安裝時會根據當前系統的配置選擇默認的 driver。默認 driver 具有最好的穩定性,因爲默認 driver 在發行版上經過了嚴格的測試。
    運行Docker info可查看當前系統使用的Storage driver
    Docker學習-Docker存儲

Docker學習-Docker存儲
centos默認的driver用的是overlay2,底層的文件系統是xfs,各層數據存放在/var/lib/docker

對於某些容器如busybox只是個工具箱,不需要保存數據以後使用,使用完成後直接退出,容器刪除時存放在容器層中的工作數據也一起被刪除。

Docker數據管理

docker容器中持久化數據一般採用兩種存儲方式:
volume
bind mount
Docker學習-Docker存儲
無論是volume還是bind mount,其本質上是宿主機文件系統中的目錄或者文件
無論是volume還是bind mount,其上存放的數據生命週期對立於容器,即容器刪除之後,volume或者bind mount上的數據,依舊存在

Volume

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

  • Volume 是目錄或文件,而非沒有格式化的磁盤(塊設備)。
  • 容器可以讀寫 volume 中的數據。
  • volume 數據可以被永久的保存,即使使用它的容器已經銷燬。

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

volume使用注意事項:

  • volume的內容存在容器的生命週期之外;刪除後依舊存在
  • 掛載volume時,不需要指定mount源,指定mount point即可,Docker會在/var/lib/docker/volumes路徑下爲每個volume生成一個目錄,作爲mount源
  • 若mount point指向容器中已有的目錄,則該目錄下的數據會被copy到volume中
  • 若mount point指向容器中的空目錄,則會自動創建所需目錄。
  • 若啓動掛載上不存在的卷的容器,Dokcer會自動創建卷
  • Volume再使用時,可通過ro參數將容器戳volume的權限設置爲只讀

bind mount

bind mount 是將 host 上已存在的目錄或文件 mount 到容器。
Docker學習-Docker存儲

bind mount實際上是一個inode替換的過程。

bind mount機制主要作用,允許一個目錄或者文件(不是整個設備)掛載到一個指定的目錄上,而且在該掛載點上進行任何的操作,只是發生在被掛載的目錄或者文件上,而原掛載點的內容則會被隱藏起來不受影響。

bind mount使用注意事項:

  • 容器運行過程中,對bind mount目錄中改動的數據,將被保存,刪除容器後,bind mount中的數據任然存在。
  • bind mount可以掛載在一個目錄到容器,也可以掛載一個文件到容器,但必須要指定的目錄或文件的路徑,即mount源,當然也必須指定mount point,這也限制了容器的可移植性
  • 若將bind mount也綁定到容器上的某非空目錄下,則會隱藏容器目錄下的現有內容,若不希望容器的整個目錄被覆蓋,可單獨掛載某個文件
  • 若mount源指向的文件或者目錄在宿主機上不存在,則會自動創建
  • bind mount時,可以通過ro參數將容器對數據的權限設置爲只讀,設置ro參數後,容器無法對數據進行修改,但宿主機依舊有權修改其內容。

bind mount的用法是使用-v選項將host已經存在的目錄或者文件mount到容器
如下所示:
Docker學習-Docker存儲

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

數據共享

數據共享是volume的關鍵特性,主機與容器數據共享:

  • bind mount:將host上的目錄或者文件mount到容器中
  • volume:將Host上的數據copy到容器的volume中
    容器間的數據共享:
    bind mount:將host上目錄或文件mount到多個容器中
    volume:將volume掛載到多個容器
    volume container:先通過volume或bind mount將數據掛載到一個container中,其他容器再引用這個container中的數據

volume container是專門爲其他容器提供volume的容器。

volume生命週期管理

備份

因爲 volume 實際上是 host 文件系統中的目錄和文件,所以 volume 的備份實際上是對文件系統的備份

恢復

volume 的恢復也很簡單,如果數據損壞了,直接用之前備份的數據拷貝

遷移

如果使用更新版本的 Registry,這就涉及到數據遷移,方法是:

  • docker stop 當前 Registry 容器。
  • 啓動新版本容器並 mount 原有 volume。

銷燬

volume刪除後數據是找不回來的,注意
docker 不會銷燬 bind mount,刪除數據的工作只能由 host 負責,再在執行 docker rm 刪除容器時可以帶上 -v 參數,docker 會將容器使用到的 volume 一併刪除,但前提是沒有其他容器 mount 該 volume。

操作實驗

volume掛載操作

創建一個卷,並掛載一個httpd容器
docker run -d -p 8080:80 -v /usr/local/apache2/htdocs httpd
-v 將其mount到httpd容器
Docker學習-Docker存儲
-v格式爲<host path>:<container path>。/usr/local/apache2/htdocs就是Apache Server存放靜態文件的地方,
由於 /usr/local/apache2/htdocs 已經存在,原有數據會被隱藏起來,取而代之的是 host $HOME/htdocs/ 中的數據。
檢查volume信息

docker volume ls

Docker學習-Docker存儲

查看容器的volume掛載信息,同時得到volume路徑,Type=volume

docker inspect d5db6a048612

Docker學習-Docker存儲

查看volume中的數據

 cd /var/lib/docker/volumes/6189c90831d019229a2e8593453fe1c334faec1fcc56db80b9f99773d21c9c55/_data

Docker學習-Docker存儲

查看容器中相應的數據,結果:容器中的數據=volume中數據
Docker學習-Docker存儲

進入容器更新index.html文件內容

docker exec -it d5db6a048612 bash
cd htdocs && echo "update the index" > index.html

Docker學習-Docker存儲
再次查看volume中的內容,已經同步跟新
Docker學習-Docker存儲
由此實現容器和Host的數據共享。

強制刪除容器,然後查看volume中的數據,可以看到依舊存在

docker rm -f d5db6a048612

Docker學習-Docker存儲

bind mount

將宿主機的/root/htdocs目錄以只讀的方式掛載給一個名爲httpd1的httpd容器,映射端口8081

docker run --name httpd1 -d -p 8081:80 -v /root/htdocs:/usr/local/apache2/htdocs:ro httpd

Docker學習-Docker存儲

查看容器掛載信息。Type=bind

docker inspect httpd1

Docker學習-Docker存儲

在宿主機host上跟新index.html文件數據,印證httpd1容器中的數據也一起跟新
Docker學習-Docker存儲
由此 ,容器和Host的實現了數據共享

進入httpd1容器中更新index.html文件數據,提示Read-only
Docker學習-Docker存儲

將宿主機/root/htdocs掛載給名爲httpd2的http容器,映射端口8082,不設置ro

docker run --name httpd2 -d -p 8082:80 -v /root/htdocs/:/usr/local/apache2/htdocs httpd

Docker學習-Docker存儲
進入httpd2容器中更新index.html

docker exec -it httpd2 bash

Docker學習-Docker存儲

分別查看宿主機、http1,http2中的數據,三者數據一致
Docker學習-Docker存儲
此時印證容器間的數據實現共享

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