一、容器数据卷简述

数据卷(Data Volumes)是一个可供一个或多个容器使用的特殊目录,它将主机操作系统目录直接映射进容器。

使用docker容器的时候,会产生一系列的数据文件,这些数据文件在删除docker容器时是会消失的,但是其中产生的部分内容是希望能够把它给保存起来另作用途的,Docker将应用与运行环境打包成容器发布,程序员希望在运行过程钟产生的部分数据是可以持久化的的,而且容器之间我们希望能够实现数据共享。

一般地来说,docker 容器数据卷可以看成常用的u盘,它存在于一个或多个的容器中,由 docker 挂载到容器,但不属于联合文件系统,Docker 不会在容器删除时删除其挂载的数据卷。

二、数据卷特点

  • 数据卷可以在容器之间共享或重用数据
  • 数据卷中的更改可以立即生效
  • 数据卷中的更改不会包含在镜像的更新中
  • 数据卷默认会一直存在,即使容器被删除
  • 数据卷的生命周期一直持续到没有容器使用它为止

三、数据卷注意事项

  • 挂载数据卷,最好是通过run而非 create/start 创建启动容器,create/start命令创建启动容器 后,再挂载数据卷相当麻烦,要修改很多配置文件,但并非不可以。
  • docker官网推荐尽量进行目录挂载,不要进行文件挂载。

四、数据卷类型

docker_volume

1、bind mount(绑定挂载)

bind mounts : 容器内的数据被存放到宿主机文件系统的任意位置,甚至存放到一些重要的系统目录或 文件中。除了docker之外的进程也可以任意对他们进行修改。

当使用bind mounts时,宿主机的目录或文件被挂载到容器中。容器将按照挂载目录或文件的绝对路径 来使用或修改宿主机的数据。宿主机中的目录或文件不需要预先存在,在需要的使用会自动创建。

使用bind mounts在性能上是非常好的,但这依赖于宿主机有一个目录妥善结构化的文件系统。

使用bind mounts的容器可以在通过容器内部的进程对主机文件系统进行修改,包括创建,修改和删除 重要的系统文件和目录,这个功能虽然很强大,但显然也会造成安全方面的影响,包括影响到宿主机上 Docker以外的进程。

注意事项

  • 如果挂载一个空的数据卷到容器中的一个非空目录中,那么这个目录下的文件会被复制到数据卷中。
  • 如果挂载一个非空的数据卷到容器中的一个目录中,那么容器中的目录会显示数据卷中的数据。如果原来容器中的目录有数据,那么原始数据会被隐藏掉。

示例:创建 nginx 容器,并进行 bind mount 挂载。

1
2
docker run -it --mount type=bind,source=/usr/local/data,destination=/data --name nginx01 nginx /bin/bash
docker run -it -v /usr/local/data:/data --name nginx01 nginx /bin/bash

查看容器挂载细节

1
docker inspect nginx01
1
2
3
4
5
6
7
8
9
10
"Mounts": [
{
"Type": "bind",
"Source": "/usr/local/data",
"Destination": "/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],

2、volume mount(数据卷挂载)

当我们创建一个数据卷时,它存储在 Docker 主机上的一个目录中。数据卷由 Docker 管理,并与主机的核心功能隔离。

给定的数据卷可以同时安装到多个容器中。当没有正在运行的容器使用数据卷时,数据卷仍然可供 Docker 使用,并且不会自动删除。

当我们挂载一个数据卷时,它可能是命名的或匿名的。匿名数据卷在首次挂载到容器时没有明确的名称,因此 Docker 给它们一个随机名称,保证在给定的 Docker 主机中是唯一的。除了名称之外,命名卷和匿名卷的行为方式相同。

示例:创建 nginx 容器,并进行 volume 挂载。

1
docker run -it --mount type=volume,source=my-data2,destination=/data --name nginx02 nginx /bin/bash

查看挂载细节

1
docker inspect nginx02
1
2
3
4
5
6
7
8
9
10
11
12
"Mounts": [
{
"Type": "volume",
"Name": "my-data1",
"Source": "/var/lib/docker/volumes/my-data1/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],

3、tmpfs mount(临时挂载)

tmpfs 挂载只存储在宿主机系统的内存中,从不写入宿主机系统的文件系统。它不会保存在磁盘上,无论是在 Docker 主机上还是在容器内。

tmpfs mount 可以在容器的生命周期内用于存储非持久状态或敏感信息。

示例:创建 nginx 容器,并进行tmpfs 挂载。

1
docker run -it --mount type=tmpfs,destination=/data --name nginx03 nginx /bin/bash

查看挂载细节

1
docker inspect nginx03
1
2
3
4
5
6
7
8
9
10
"Mounts": [
{
"Type": "tmpfs",
"Source": "",
"Destination": "/data",
"Mode": "",
"RW": true,
"Propagation": ""
}
],

五、数据卷挂载命令

--volume (简写 -v)--mount 参数用于数据卷挂载。

1、创建 bind mount 和挂载 volume 的比较

对比项 bind mount volume
Source位置 用户指定 /var/lib/docker/volumes/
Source为空 覆盖dest为空 保留dest内容
Source非空 覆盖dest内容 覆盖dest内容
Source种类 文件或目录 只能是目录
可移植性 一般(自行维护) 强(docker托管)
宿主直接访问 容易(仅需chown) 受限(需登陆root用户)*

2、创建 bind mount 时使用--volume--mount的比较

对比项 --volume-v --mount type=bind
如果主机路径不存在 自动创建 命令报错

六、匿名数据卷

匿名数据卷:不指定本地挂载路径,只指定容器内挂载路径,本地挂载路径在 /var/lib/docker 自动生成。

示例:

1
docker run -it -v /data --name nginx05 nginx /bin/bash

查看容器内部细节:

1
2
3
4
5
6
7
8
9
10
11
12
"Mounts": [
{
"Type": "volume",
"Name": "818aa9dff871110fc02096eec9234595ef3758004c92b0de617444ac85a4df08",
"Source": "/var/lib/docker/volumes/818aa9dff871110fc02096eec9234595ef3758004c92b0de617444ac85a4df08/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],

七、只读和读写

容器数据卷的只读和读写需要通过参数 rorw 来进行控制。

  • ro :read only

  • rw :read write

语法格式:

1
2
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
docker run -it -v /宿主机绝对路径目录:/容器内目录:rw 镜像名

示例:

1
2
docker run -d -P --name nginx05 -v nginx1:/etc/nginx:ro nginx
docker run -d -P --name nginx05 -v nginx2:/etc/nginx:rw nginx

注意:只要看到 ro 就说明这个路径只能通过宿主机来操作,容器内部是无法操作!

八、数据卷继承与共享

命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器,容器之间的数据卷可以通过 --volumes-form 参数共享数据。

img

1、环境准备

(1)创建启动 c3 数据卷容器,使用 –v 参数 设置数据卷。

1
docker run -it --name=c3 -v /test:/data centos:7 /bin/bash

(2)创建启动 c1 容器,使用 --volumes-from 参数设置数据卷继承 c3 数据卷。

1
docker run -it --name=c1 --volumes-from c3 centos:7 /bin/bash

(3)创建启动 c2 容器,使用 --volumes-from 参数设置数据卷继承 c3 数据卷。

1
docker run -it --name=c2 --volumes-from c3 centos:7 /bin/bash

2、分别连接三个容器和主机

通过下图查看数据卷,可以发现三个容器的挂载点 /data 和主机 /test 目录均为空。

image-20220804143151879

3、在本机创建文件,其他三台容器是否可以查看到此文件?

image-20220804143006744

结论:在主机创建文件,容器中可以查看到。

4、在容器数据卷中创建文件,在主机是否可以查看呢?

image-20220804143415467

结论:在容器内创建文件,在主机也可查看。

5、停止容器 c3 ,继承容器 c3 的容器 c1 、 c2 和主机之间数据还可以共享吗?

image-20220804143856452

结论:

  • 容器之间配置信息的传递,存储在本机的文件则会一直保留!
  • 数据卷的生命周期一直持续到没有容器使用它为止。
  • 一旦持久化到了本地,本地的数据是不会删除的!

九、参考文档

全网最详细的docker数据卷教程 - 掘金 (juejin.cn)

Docker数据卷挂载命令volume(-v)与mount的区别

Docker数据卷及网络详细讲解

Docker 数据卷和Dockerfile (icode9.com)