docker 容器运行时所产生的数据都会随 docker 容器删除而被删除,很多时候我们希望将容器中产生的数据保存下来,比如日志文件等。这时候可以通过捆绑挂载(bind-mount)与数据卷(volume)两种方式将容器内部数据挂载到容器的宿主机中。不管是数据卷还是捆绑挂载,都可以和本机共享目录。
docker 中可使用的指令有两种 -v
和 --mount
,这两种指令的演示下面都有。
捆绑挂载
捆绑挂载,我理解就是直接指定宿主机的 A 目录与容器的 B 目录进行捆绑。
demo-server
镜像可自己定制,参考 制作镜像示例
# 不进行宿主机目录挂载
docker run -d -p 80:8080 --name demo1 demo-server
# 使用 -v 将容器的 /var/lib 目录挂载到宿主机的 /dockerDir/demo2
docker run -d \
-p 81:8080 \
--name demo2 \
-v /dockerDir/demo2:/var/lib \
demo-server
# 使用 --mount 将容器的 /var/lib 目录挂载到宿主机的 /dockerDir/demo3
docker run -d \
-p 82:8080 \
--name demo3 \
--mount type=bind,source=/dockerDir/demo3,target=/var/lib \
demo-server
# --mount 还可以指定挂载目录的读写权限,默认为读写,使用 readonly 指定为只读
--mount type=bind,source=/dockerDir/demo3,target=/var/lib,readonly \
-v
--mount
的区别:
-v:
- 只能挂载目录
- 挂载的宿主机目录不存在会自动创建
--mount:
- 可以挂载目录和文件
- 挂载的宿主机目录必须存在,否则会报错
- 可以指定读写权限,通过
readonly
指定为只读
启动了上面三个容器之后,我们可以通过 docker inspect "容器ID或名称"
查看容器的详细信息,其中的 Mounts
属性就是挂载信息。
因为 demo1 没有挂载到宿主机目录,所以 Mounts 信息为空
# demo1
"Mounts": []
# demo2
"Mounts": [
{
"Type": "bind",
"Source": "/dockerDir/demo2",
"Destination": "/var/lib",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
]
# demo3
"Mounts": [
{
"Type": "bind",
"Source": "/dockerDir/demo3",
"Destination": "/var/lib",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
]
数据卷 (volume)
数据卷
是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
数据卷
可以在容器之间共享和重用- 对
数据卷
的修改会立马生效 - 对
数据卷
的更新,不会影响镜像 数据卷
默认会一直存在,即使容器被删除
注意:
数据卷
的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的数据卷
。
数据卷
是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷
,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷
。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v
这个命令。
下面是 volume 常用命令:
# 查看所有volume
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
# 创建一个名为demo-volume的数据卷
[root@localhost ~]# docker volume create demo-volume
demo-volume
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local demo-volume
# 查看demo-volume详细信息
[root@localhost ~]# docker volume inspect demo-volume
[
{
"CreatedAt": "2020-03-11T10:33:22+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/demo-volume/_data",
"Name": "demo-volume",
"Options": {},
"Scope": "local"
}
]
# 删除volume
[root@localhost demo3]# docker volume rm demo-volume
demo-volume
# 删除所有无主volume,即没有被容器使用到的
docker volume prune
根据详细信息中 Mountpoint
属性得知,我们创建的数据卷在宿主机中的目录为 /var/lib/docker/volumes/demo-volume/_data
,所有创建的数据卷都会在 /var/lib/docker/volumes
这个目录下。也就是说,我们使用数据卷挂载容器目录,实际就是将容器的某个目录挂载到宿主机的这个目录中。
有了数据卷之后,我们可以使用下面的命令将容器目录挂载起来:
# 使用 -v
docker run -d \
-p 81:8080 \
--name demo2 \
-v demo-volume:/var/lib \
demo-server
# 使用 --mount
docker run -d \
-p 81:8080 \
--name demo3 \
--mount source=demo-volume,target=/var/lib \
demo-server
-- end --