(2)Docker 映象
(3)Docker 容器的隔離性 - 使用 Linux namespace 隔離容器的執行環境
(4)Docker 容器的隔離性 - 使用 cgroups 限制容器使用的資源
(5)Docker 網路
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 上有很多指令碼可以自動化地清理孤單卷,比如:
- https://github.com/chadoe/docker-cleanup-volumes/blob/master/docker-cleanup-volumes.sh
- https://github.com/meltwater/docker-cleanup
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 的結構: