docker managed volume 与 bind mount在使用上的最大区别是不需要指定 mount 源,指明 mount point 就行了。以busybox容器为例:
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
[root@localhost ~]# docker run -itd --name=busybox -v /etc/managed busybox
c465fa1717dd1da27765ed85f8eb57b96ffba85d41d36bd3b091bd7d44e49d05
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c465fa1717dd busybox "sh" 11 seconds ago Up 8 seconds busybox
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local a2ddf154e5e224acc154d4895017b65d310f6ca430fadd89ff5d3630e8939e7c
我们通过 -v
告诉 docker 需要一个 data volume,并将其 mount 到/etc/managed 。那么这个data volume 具体在哪儿呢?
这个答案可以在容器的配置信息中找到,执行 docker inspect
命令:
[root@localhost ~]# docker inspect busybox
...........................................................
"Mounts": [
{
"Type": "volume",
"Name": "a2ddf154e5e224acc154d4895017b65d310f6ca430fadd89ff5d3630e8939e7c",
"Source": "/var/lib/docker/volumes/a2ddf154e5e224acc154d4895017b65d310f6ca430fadd89ff5d3630e8939e7c/_data",
"Destination": "/etc/managed",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
..............................................................
docker inspect
的输出很多,我们感兴趣的是 Mounts
这部分,这里会显示容器当前使用的所有 data volume,包括 bind mount 和 docker managed volume。
Source
就是该 volume 在 host 上的目录。
[root@localhost ~]# cd /var/lib/docker/volumes/a2ddf154e5e224acc154d4895017b65d310f6ca430fadd89ff5d3630e8939e7c/_data
[root@localhost _data]# ls
[root@localhost _data]# touch a.txt
[root@localhost _data]# docker exec -it busybox ls /etc/managed
a.txt
原来,每当容器申请 mount docker manged volume 时,docker 都会在/var/lib/docker/volumes
下生成一个目录(例子中是 "/var/lib/docker/volumes/a2ddf154e5e224acc154d4895017b65d310f6ca430fadd89ff5d3630e8939e7c/_data" ),这个目录就是 mount 源。
明确一点:此时的 /usr/local/apache2/htdocs 已经不再是由 storage driver 管理的层数据了,它已经是一个 data volume。我们可以像 bind mount 一样对数据进行操作,例如更新数据。
简单回顾一下 docker managed volume 的创建过程:
-
容器启动时,简单的告诉 docker "我需要一个 volume 存放数据,帮我 mount 到目录 /abc"
-
docker 在 /var/lib/docker/volumes 中生成一个随机目录作为 mount 源
-
如果 /abc 已经存在,则将数据复制到 mount 源
-
将 volume mount 到 /abc
注意如果你要mount的目录下已经存在了文件,这些文件还是会显示出来不会被隐藏起来,这个和bind mount是不同的
[root@localhost ~]# docker run -itd -v /etc/nginx/ nginx
ee81653a884cff75bdcfae540e814fca19e25b64d546a1ff1761892d227028e5
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee81653a884c nginx "/docker-entrypoint.…" 4 seconds ago Up 2 seconds 80/tcp charming_northcutt
[root@localhost ~]# docker exec -it ee81653a884c /bin/bash
root@ee81653a884c:/# cd /etc/nginx/
root@ee81653a884c:/etc/nginx# ls
conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf
[root@localhost ~]# docker inspect ee81653a884c
"Mounts": [
{
"Type": "volume",
"Name": "b923a5a77222defdc83ebd03b79ea121d87d9296535b9d335828a91b2d7d5a2c",
"Source": "/var/lib/docker/volumes/b923a5a77222defdc83ebd03b79ea121d87d9296535b9d335828a91b2d7d5a2c/_data",
"Destination": "/etc/nginx",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
[root@localhost ~]# cd /var/lib/docker/volumes/b923a5a77222defdc83ebd03b79ea121d87d9296535b9d335828a91b2d7d5a2c/_data
[root@localhost _data]# ls
conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf
我们已经学习了两种 data volume 的原理和基本使用方法,下面做个对比:
-
相同点:两者都是 host 文件系统中的某个路径。
-
不同点:
bind mount | docker managed volume | |
---|---|---|
volume 位置 | 可任意指定 | /var/lib/docker/volumes/... |
对已有mount point 影响 | 隐藏并替换为 volume | 原有数据复制到 volume |
是否支持单个文件 | 支持 | 不支持,只能是目录 |
权限控制 | 可设置为只读,默认为读写权限 | 无控制,均为读写权限 |
移植性 | 移植性弱,与 host path 绑定 | 移植性强,无需指定 host 目录 |
下篇博客讨论如何通过 data volume 实现容器与 host,容器与容器共享数据。