理解Docker(8):Docker 存儲之卷(Volume)


(1)Docker 安裝及基本用法

(2)Docker 鏡像

(3)Docker 容器的隔離性 - 使用 Linux namespace 隔離容器的運行環境

(4)Docker 容器的隔離性 - 使用 cgroups 限制容器使用的資源

(5)Docker 網絡

(6)若干企業生產環境中的容器網絡方案

(7)Docker 存儲 - AUFS

(8)Docker 存儲 - Volume

 

1. Docker volume 的幾種形態

    有狀態容器都有數據持久化需求。前一篇文章中提到過,Docker 采用 AFUS 分層文件系統時,文件系統的改動都是發生在最上面的容器層。在容器的生命周期內,它是持續的,包括容器在被停止后。但是,當容器被刪除后,該數據層也隨之被刪除了。因此,Docker 采用 volume (卷)的形式來向容器提供持久化存儲。Docker volume 有如下幾種形態。

1.1 無 - 不使用 Docker volume

默認情況下,容器不使用任何 volume,此時,容器的數據被保存在容器之內,它只在容器的生命周期內存在,會隨着容器的被刪除而被刪除。當然,也可以使用 docker commit 命令將它持久化為一個新的鏡像。

1.2 Data volume (數據卷)

一個 data volume 是容器中繞過 Union 文件系統的一個特定的目錄。它被設計用來保存數據,而不管容器的生命周期。因此,當你刪除一個容器時,Docker 肯定不會自動地刪除一個volume。有如下幾種方式來使用 data volume:

(1)使用 “-v 容器內目錄” 形式

docker run -d -P --name web -v /webapp training/webapp python app.py

使用 docker inspect 命令可以看出,Docker 將本地一個 _data 目錄 mount 為容器內的 webapp 目錄了:

"Mounts": [
            {
                "Name": "f143b7f379fb6d012a08656fc950bf6df4bf5a5b90c72f310644aa997620122b",
                "Source": "/var/lib/docker/volumes/f143b7f379fb6d012a08656fc950bf6df4bf5a5b90c72f310644aa997620122b/_data",
                "Destination": "/webapp",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

其實,在 web 容器被刪除后,/var/lib/docker/volumes/f143b7f379fb6d012a08656fc950bf6df4bf5a5b90c72f310644aa997620122b/_data 目錄及其中的內容都還會保留下來,但是,新啟動的容器無法再使用這個目錄,也就是說,已有的數據不能自動地被重復使用了。

(2)使用 -v 來掛載一個主機上的目錄到容器的目錄

docker run -d -P --name web2 -v /src/webapp:/webapp training/webapp python app.py

主機上的目錄可以是一個本地目錄,也可以在一個 NFS share 內,或者在一個已經格式化好了的塊設備上。

其實這種形式和第一種沒有本質的區別,容器內對 /webapp 的操作都會反映到主機上的 /src/webapp 目錄內。只是,重新啟動容器時,可以再次使用同樣的方式來將 /src/webapp 目錄掛載到新的容器內,這樣就可以實現數據持久化的目標。

(3)使用 -v 來掛載主機上的一個文件到容器內的一個文件

docker run --rm -it -v ~/.bash_history:/root/.bash_history ubuntu /bin/bash

1.3 使用 data container

如果要在容器之間共享數據,最好是使用 data container。這種 container 中不會跑應用,而只是掛載一個卷。比如:

創建一個 data container:

docker create -v /dbdata --name dbstore training/webapp  /bin/true

啟動一個 app container:

docker run -d -P --name web3 --volumes-from dbstore training/webapp python app.py

其實,對 web3 這個容器來說,volume 的本質沒變,它只是將 dbstore 容器的 /dbdata 目錄映射的主機上的目錄映射到自身的 /dbdata 目錄。

"Mounts": [
            {
                "Name": "5341c03f3b94f13f4c86d88ccb0f3b63487adf30dea7ae6b2d06e947235e7330",
                "Source": "/var/lib/docker/volumes/5341c03f3b94f13f4c86d88ccb0f3b63487adf30dea7ae6b2d06e947235e7330/_data",
                "Destination": "/dbdata",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

但是,其好處是,可以不管其目錄的臨時性而不斷地重復使用它。

1.4 使用 docker volume 命令

Docker 新版本中引入了 docker volume 命令來管理 Docker volume。

(1)使用默認的 ‘local’ driver 創建一個 volume

root@docker1:/home/sammy# docker volume create --name vol1
vol1
root@docker1:/home/sammy# docker volume inspect vol1
[
    {
        "Name": "vol1",
        "Driver": "local",
        "Mountpoint": "/var/lib/docker/volumes/vol1/_data",
        "Labels": {},
        "Scope": "local"
    }
]

(2)使用這個 volume

docker run -d -P --name web4 -v vol1:/volume training/webapp python app.p

結果還是一樣的,即將 vol1 對應的主機上的目錄掛載給容器內的 /volume 目錄。

"Mounts": [
            {
                "Name": "vol1",
                "Source": "/var/lib/docker/volumes/vol1/_data",
                "Destination": "/volume",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

1.5 Volume 刪除和孤單 volume 清理

1.5.1 在刪除容器時刪除 volume

可以使用 docker rm -v 命令在刪除容器時刪除該容器的卷。

root@docker1:/home/sammy# docker run -d -P --name web5 -v /webapp training/webapp python app.py
69199905a74cb360935e32f4e99f7f11319f6aa36033a920aa0bae25874f5c69
root@docker1:/home/sammy# docker volume ls
DRIVER              VOLUME NAME
local               5341c03f3b94f13f4c86d88ccb0f3b63487adf30dea7ae6b2d06e947235e7330
local               838f4dd99721a9445be22a6b42d35e04cb43ad145ecf26107a9025f428587f76
local               vol1
root@docker1:/home/sammy# docker rm -vf web5
web5
root@docker1:/home/sammy# docker volume ls
DRIVER              VOLUME NAME
local               5341c03f3b94f13f4c86d88ccb0f3b63487adf30dea7ae6b2d06e947235e7330
local               vol1

1.5.2 批量刪除孤單 volumes

從上面的介紹可以看出,使用 docker run -v 啟動的容器被刪除以后,在主機上會遺留下來孤單的卷。可以使用下面的簡單方法來做清理:

root@docker1:/home/sammy# docker volume ls -qf dangling=true
244a23f3ab11f17345a68e77f96bb46a8dbaf445760dd86ab0faa07dfbd84236
c864cfac232e8728b1805abc8c363d324124b38e6297544a8cbbf61d883c7e46
f143b7f379fb6d012a08656fc950bf6df4bf5a5b90c72f310644aa997620122b
root@docker1:/home/sammy# docker volume rm $(docker volume ls -qf dangling=true)
244a23f3ab11f17345a68e77f96bb46a8dbaf445760dd86ab0faa07dfbd84236
c864cfac232e8728b1805abc8c363d324124b38e6297544a8cbbf61d883c7e46
f143b7f379fb6d012a08656fc950bf6df4bf5a5b90c72f310644aa997620122b
root@docker1:/home/sammy# docker volume ls
DRIVER              VOLUME NAME
local               5341c03f3b94f13f4c86d88ccb0f3b63487adf30dea7ae6b2d06e947235e7330
local               vol1

github 上有很多腳本可以自動化地清理孤單卷,比如:

1.6 小結

對以上內容的兩點小結:

  • 容器內的數據是臨時性的,它會隨着容器生命周期的結束而消失
  • 默認的 Docker volume (driver = ‘loclal’)不管是哪種形式,本質上都是將容器所在的主機上的一個目錄 mount 到容器內的一個目錄,因此,它不具備可移植性。

2. Flocker:容器的分布式存儲平台

第一部分提到過,原生的 Docker volume 不具備可移植性。於是,出現了Docker 的分布式卷解決方案 Flocker。先來看看 Flocker volume 和 Docker 原生 volume 的對比:

啟動一個使用 Flocker 卷的容器:

docker run --volume-driver flocker -v flocker-volume:/container/dir --name=container-xyz

它帶來的好處包括:

  • 容器的數據會被寫入 Flocker 后端存儲而不是主機上,因此,在主機出現故障時可以保證數據不丟失
  • 在容器遷移時,Flocker 會自動地將卷從一個 host 移植到另一個 host

Flocker 的結構:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM