Docker卷管理入门

数据卷

Docker的镜像使用UFS(Uion File System),UFS虽适合于构建和共享镜像,但对于存储持久数据或共享数据的需求来说,卷才是更好的选择。简单来说,卷就是容器目录树上的一个用作挂载点的目录,它用于挂载主机目录树上的某个目录,换句话讲,卷并非UFS的目录树,而是绑定的主机上的某目录树。事实上,卷是独立于容器生命周期之外的用于数据分段及共享的组件。

Docker卷管理入门

实践中,镜像文件保存了各种静态数据,例如应用程序本身,而卷则保存各种动态数据,例如应用程序处理或生成的数据。如此一来,卷的引入可以使得容器和数据相分离,从而构建出一个模块化结构,并实现了类似“多态”的模型——基于同一个镜像运行的容器可以处理不同的数据。

卷类型

Docker支持两种类型的卷,一种为“Docker管理卷(Docker-managed volumes)”,创建时仅需要指定容器中的挂载点,主机上被绑定挂载的目录由Docker进程负责创建,这也是其名称由来的原因;另一种是“绑定挂载卷(Bind mount volumes)”,创建时既要指定容器中的挂载点,也要指定主机上的被挂载目录。

Docker卷管理入门

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)”。这么做的主要好处在于为其它容器提供一个易于掌控的卷名称空间,并有助于容器迁移。

相关新闻

历经多年发展,已成为国内好评如潮的Linux云计算运维、SRE、Devops、容器云、Go、Python开发专业人才培训机构!