Docker卷管理入門
數據卷
Docker的鏡像使用UFS(Uion File System),UFS雖適合于構建和共享鏡像,但對于存儲持久數據或共享數據的需求來說,卷才是更好的選擇。簡單來說,卷就是容器目錄樹上的一個用作掛載點的目錄,它用于掛載主機目錄樹上的某個目錄,換句話講,卷并非UFS的目錄樹,而是綁定的主機上的某目錄樹。事實上,卷是獨立于容器生命周期之外的用于數據分段及共享的組件。
實踐中,鏡像文件保存了各種靜態數據,例如應用程序本身,而卷則保存各種動態數據,例如應用程序處理或生成的數據。如此一來,卷的引入可以使得容器和數據相分離,從而構建出一個模塊化結構,并實現了類似“多態”的模型——基于同一個鏡像運行的容器可以處理不同的數據。
卷類型
Docker支持兩種類型的卷,一種為“Docker管理卷(Docker-managed volumes)”,創建時僅需要指定容器中的掛載點,主機上被綁定掛載的目錄由Docker進程負責創建,這也是其名稱由來的原因;另一種是“綁定掛載卷(Bind mount volumes)”,創建時既要指定容器中的掛載點,也要指定主機上的被掛載目錄。
Docker管理卷
由于主機上被綁定掛載的目錄是由Docker守護進程管理,因此,在運行docker run或docker create命令時使用“-v CONTAINER_DIR”選項即可使用此類卷。例如:
~]# docker run -it --name c1 -h container1 -v /data centos [root@container1 /]# ls /data
而后在主機上運行inspect命令來查看綁定的卷。在此示例中,容器中的/data/其實就是個映射到主機上的/var/lib/docker/volumes/cb2f80b99fcb201255b365c727f2856fec44ea1b00143f46ebd2f13f77e82543/_data目錄的鏈接,如下所示。
~]# docker inspect -f "{{.Mounts}}" c1 [{cb2f80b99fcb201255b365c727f2856fec44ea1b00143f46ebd2f13f77e82543 /var/lib/docker/volumes/cb2f80b99fcb201255b365c727f2856fec44ea1b00143f46ebd2f13f77e82543/_data /data local true }]
此時,在主機上的/var/lib/docker/volumes/cb2f80b99fcb201255b365c727f2856fec44ea1b00143f46ebd2f13f77e82543/_data目錄中創建的文件,可直接通過容器的/data/路徑進行訪問。例如,在主機上創建文件:
~]# touch /var/lib/docker/volumes/cb2f80b99fcb201255b365c727f2856fec44ea1b00143f46ebd2f13f77e82543/_data/testfile
而后,在容器中查看。
[root@container1 /]# ls /data/ testfile
需要注意的是,如果為docker rm命令刪除容器時不會刪除其卷在主機上綁定的目錄,除非使用了-v選項。
綁定掛載卷
與Docker管理卷僅有的不同是,綁定掛載卷(后面簡稱綁定卷)需要用戶在指定容器中掛載點的同時,指定主機上某事先存的被掛載目錄,其選項使用格式為“-v HOST_DIR:CONTAINER_DIR”。例如,綁定容器中的/data至主機上的/data/web/shop:
~]# docker run -it --name c2 -h container2 -v /data/web/shop:/data centos [root@container2 /]#
在主機上查看綁定的結果:
~]# docker inspect -f "{{.Mounts}}" c2 [{ /data/web/shop /data true rprivate}]
刪除此類容器時,卷在主機上綁定的相關目錄不會被刪除,即使使用了-v選項也不成。
~]# docker stop c2 ~]# docker rm -v c2 ]# ls -ld /data/web/shop/ drwxr-xr-x 2 root root 6 Mar 18 23:59 /data/web/shop/
另外,此種類型的卷不僅可以綁定目錄,也可以綁定文件,不過主機一側的文件需要事先存在,否則,Docker會將其理解為目錄,并自動創建之。
~]# docker run -it --name c3 -h container3 -v /etc/issue:/tmp/issue centos [root@container3 /]# cat /tmp/issue S Kernel r on an m
共享卷
上述第二種方式中的“-v HOST_DIR:CONTAINER_DIR”選項常用于在主機和一個或多個容器間共享數據。例如,需要讓兩個容器訪問同一組數據時,只需要將容器中的路徑綁定至主機上的同一個目錄即可。
~]# docker run --rm -it --name c1 -h container1 -v /tmp/doc:/doc centos [root@container1 /]# cp /etc/hosts /doc/
~]# docker run --rm -it --name c2 -h container2 -v /tmp/doc:/doc centos [root@container2 /]# cat /doc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 container1
另外,docker run命令在啟動容器時,也可以使用“--volumes-from <CONTAINER>”選項來訪問(復制)指定的容器的卷,例如:
~]# docker run --rm -it --name c1 -h container1 -v /tmp/doc:/doc centos [root@container1 /]# cp /etc/hosts /doc/
~]# docker run --rm -it --name c2 -h container2 --volumes-from c1 centos [root@container2 /]# ls /doc/ hosts [root@container2 /]# cat /doc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 container1
查看新創建的容器c2的卷,可以發現,其復制了--volumes-from選項中指定的容器的卷定義。
[root@docker ~]# docker inspect -f "{{.Mounts}}" c2 [{ /tmp/doc /doc true rprivate}]
實踐中,如果一容器存在的惟一目的是為其它容器提供共享數據的話,此容器即為“數據容器(data containers)”。這么做的主要好處在于為其它容器提供一個易于掌控的卷名稱空間,并有助于容器遷移。