接触 docker 的朋友都知道,docker 镜像是以 layer 概念存在的,一层一层的叠加,最终成为我们需要的镜像。但该镜像的每一层都是 ReadOnly 只读的。只有在我们运行容器的时候才会创建读写层。文件系统的隔离使得:
docker提供了三种不同的方式将数据挂载到容器中,volume、bind mount(-v映射)、tmpfs
volume方式是docker中数据持久化的最佳方式
[root@localhost ~]# ls /var/lib/docker/volumes/
ea73bac7843b4d05c08dc758ef15a5b3fc1070f3de8b3361dd40c3c58247c98f
ffa4846b581c1a50a01e7a12a6342ad2aaa442701a35ae56ef2f0e5d7888b22c
volume在docker中被推荐为首选方式,它与bind mount(-v)相比,有以下优点:
[root@localhost ~]# docker volume create my-vol 创建卷
my-vol
[root@localhost ~]# docker volume ls 查看卷列表
DRIVER VOLUME NAME
local 1ad4af809485ff974988b79fdc3ada634c0b14b1324d9581369fd3b161632115
local my-vol
local portainer_data
[root@localhost ~]# docker volume inspect my-vol 查看卷信息
[
{
"CreatedAt": "2019-03-01T19:40:26+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
[root@localhost ~]# docker volume rm my-vol 删除卷
my-vol
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local 1ad4af809485ff974988b79fdc3ada634c0b14b1324d9581369fd3b161632115
local portainer_data
如下:
[root@localhost ~]# docker volume create my-vol2
my-vol2
方法一:
[root@localhost ~]# docker run -d -it --name storage-test -p 80:80 --mount source=my-vol2,target=/app nginx:latest
77d559ebcdb47e9b54b7023bbb6b7bf0a7135dc7458bb68c49311e1140251901
方法二
[root@localhost ~]# docker run -d -it --name storage-test -p 80:80 -v myvol2:/app nginx:latest
[root@localhost ~]# docker inspect storage-test
"Mounts": [
{
"Type": "volume",
"Name": "my-vol2",
"Source": "/var/lib/docker/volumes/my-vol2/_data",
"Destination": "/app",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
注:该卷有正确的 Source 和 Destination,可读写。
[root@localhost ~]# docker stop storage-test #停止容器
storage-test
[root@localhost ~]# docker rm storage-test #删除容器
storage-test
[root@localhost ~]# docker volume rm my-vol2 #删除卷
my-vol2
学习链接
当启动 service 的时候,如果 Driver 是 local 的时候,则任何容器都不能共享此数据。另外 service 只能使用 --mount 标志。
使用 volume driver
当使用 docker volume create 创建卷或启动尚未创建卷的容器的时候,可以指定卷驱动程序。
下面这个例子,首先创建独立卷时使用 volume driver,然后在启动创建新卷的容器时使用 volume driver。
初始设置
这个例子假定你有 2 个节点,第一个是 docker 主机,可以使用 SSH 连接到第二个节点。
在 docker 主机上安装 vieux/sshfx 插件:
$ docker plugin install --grant-all-permissions vieux/sshfs
使用 volume driver 创建卷
下面指定了一个 SSH 密码,但如果 2 台主机共享密钥已配置,则可以省略密码。每个 volume driver 可以有多个配置选项,使用 -o 标志指定。
$ docker volume create --driver vieux/sshfs \
-o sshcmd=test@node2:/home/test \
-o password=testpassword \
sshvolume
创建容器时使用 volume driver
这里需要注意的是,如果需要在命令中使用选项,则必须使用 --mount,而不是 -v。
$ docker run -d \
-it \
--name sshfs-container \
--volume-driver vieux/sshfs \
--mount src=sshvolume,target=/app,volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \
nginx:latest
通过 bind mount 方式,你可以将你主机上的任何文件或目录(绝对路径)挂载到容器中。
挂载的文件或目录可以被任何进程修改,因此有时候容器中修改了该文件或目录将会影响其他进程
如果挂载主机的文件或目录不存在将会自动创建。
使用该方式不能通过 命令:docker volume 管理
bind mounts,一般情况在如下方式使用:
被挂载的是一个文件,因为只有bind mount 方式可挂载文件
从主机共享配置文件到容器。默认情况,docker 会绑定类似 /etc/resolv.conf 的文件用于 DNS 的解析。
主机与容器共享源代码或构建工具。如,你可以将 Maven target/ 挂载到容器中,并且每次主机上构建 Maven 项目时,容器都可以访问重建的构件。
主机的文件或目录结构与容器所需的一致时。
如果将空文件或目录挂载到容器,容器中的该目录又有文件,那么,这些文件将会被复制到主机上的目录中。如果将非空的文件或目录挂载到容器,容器中的该目录也有文件,那么,容器中的文件将会被隐藏。
volume即volume挂载卷,-v即bind mount
类型 | -v | volume |
---|---|---|
volume 位置 | 可任意指定 | /var/lib/docker/volumes/… |
对已有挂载点影响 | 隐藏并替换为 volume | 原有数据复制到 volume |
是否支持单个文件 | 支持 | 不支持,只能是目录 |
权限控制 | 可设置为只读,默认为读写权限 | 无控制,均为读写权限 |
移植性 | 移植性弱,与host path绑定 | 移植性强,无需指定host目录 |
tmpfs,仅存储在主机系统的内存中,不会写入主机的文件系统。
tmpfs,使用它的情况一般是,对安全比较重视以及不需要持久化数据。
–tmpfs 和 --mount 的关系与前面两种方式的关系不用多说。那它们之间的差异是:
容器中使用tmps