问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Docker数据卷详解:概念、使用方法及三种类型对比

创作时间:
作者:
@小白创作中心

Docker数据卷详解:概念、使用方法及三种类型对比

引用
CSDN
1.
https://blog.csdn.net/qq_42168462/article/details/146496557

Docker数据卷是Docker容器中用于持久化存储数据的重要机制。本文将详细介绍Docker数据卷的基本概念、使用方法以及不同类型数据卷的挂载方式。通过具体的命令示例和挂载信息查询,帮助读者全面理解Docker数据卷的使用场景和特点。

一、Docker数据卷是什么

当删除Docker容器时,容器内部的文件也会随之销毁。在生产环境中,我们需要将数据持久化保存,因此产生了将容器内部的数据保存在宿主机的需求。Docker数据卷(Volume)就是为了解决以下问题而设计的:

  • 容器与主机之间、容器与容器之间共享文件
  • 容器中数据的持久化
  • 容器中的数据备份、迁移、恢复

二、Docker数据卷的使用方法

在执行docker run命令时,可以使用-v参数来指定数据卷,完成数据卷挂载。数据卷可以是命名的,也可以是匿名的。匿名卷会被赋予一个随机名称,该名称保证在给定的Docker主机内是唯一的。与命名卷一样,即使删除使用它们的容器,匿名卷也会保留下来,除非在创建容器时使用了--rm标志,在这种情况下与容器关联的匿名卷将被销毁。

匿名数据卷的使用

在启动容器时只指定容器内部的路径,不写宿主机路径。例如:

docker run -d -p 8888:80 -v /usr/share/nginx/html --name nginx-volume nginx:latest

使用docker inspect命令查看其挂载信息:

docker inspect nginx-volume | grep -A 11 "Mounts"

输出结果:

"Mounts": [
    {
        "Type": "volume",
        "Name": "538688015ecc44b37c36861c07bff24f7330b06a2d8dd396d4980a9594de461d",
        "Source": "/var/lib/docker/volumes/538688015ecc44b37c36861c07bff24f7330b06a2d8dd396d4980a9594de461d/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
],

通过查询挂载信息可知,该容器挂载了一个名称为一段哈希串的volume类型的,其在宿主的存储位置在:/var/lib/docker/volumes/538688015ecc44b37c36861c07bff24f7330b06a2d8dd396d4980a9594de461d/_data目录下,挂载的是容器内的路径:/usr/share/nginx/html

命名数据卷的使用

在启动容器时指定卷名,并绑定容器内部的路径。例如:

docker run -d -p 8800:80 -v nginx_dir:/usr/share/nginx/html --name nginx-volume2 nginx:latest

使用docker inspect命令查看其挂载信息:

docker inspect nginx-volume2 | grep -A 11 "Mounts"

输出结果:

"Mounts": [
    {
        "Type": "volume",
        "Name": "nginx_dir",
        "Source": "/var/lib/docker/volumes/nginx_dir/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "z",
        "RW": true,
        "Propagation": ""
    }
],

通过查询挂载信息可知,该容器挂载了一个名称为nginx_dir的volume类型的,其在宿主的存储位置在:/var/lib/docker/volumes/nginx_dir/_data目录下,挂载的是容器内的路径:/usr/share/nginx/html

通过这两个示例发现,不管是命名数据卷还是匿名数据卷,其存储位置都在/var/lib/docker/volumes/<数据卷名称>/_data目录下,且挂载类型均为volume。那还有没有其他的类型的数据卷挂载吗?或者说,是否可以将数据存储到宿主机的其他位置?比如,希望将容器nginx-volume3的目录指定到/home/lemon/docker_nginx_data/目录之下,因为/var/lib/docker目录存储在/根分区下,其存储空间太小,希望将数据挪动到更大的目录/home分区下。下面将介绍其他的两种类型文件绑定方式。

三、Docker存储的三种类型

如果希望将容器nginx-volume3的目录/usr/share/nginx/html指定到/home/lemon/docker_nginx_data/目录之下,就需要使用如下的方式去指定挂载:

-v /home/lemon/docker_nginx_data:/usr/share/nginx/html

示例如下:

docker run -d -p 8801:80 -v /home/lemon/docker_nginx_data:/usr/share/nginx/html --name nginx-volume3 nginx:latest

使用docker inspect命令查看其挂载信息:

docker inspect nginx-volume3 | grep -A 11 "Mounts"

输出结果:

"Mounts": [
    {
        "Type": "bind",
        "Source": "/home/lemon/docker_nginx_data",
        "Destination": "/usr/share/nginx/html",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
],

通过查询挂载信息可知,该容器将宿主机的/home/lemon/docker_nginx_data目录与容器的/usr/share/nginx/html挂载了起来。与上面的两个类型相比较,我们发现其Type参数类型为bind,与上面的两种方式的volume类型不同。

volume与bind两种类型优缺点对比

对比项
Volume(卷)
Bind(绑定挂载)
存储位置
Docker统一管理,默认存放在/var/lib/docker/volumes/
直接使用宿主机上的指定目录
创建方式
通过docker volume create创建,Docker负责管理
需要手动指定宿主机路径
适用场景
推荐用于持久化存储,如数据库、日志等
适用于开发环境,可直接访问宿主机文件
容器间共享
容易共享,多个容器可以挂载同一个Volume
手动管理,需要确保宿主机目录存在
安全性
更安全,容器无法直接访问宿主机
风险较高,容器可能影响宿主机数据
性能
一般更快,Docker进行了优化
可能受文件系统性能影响
跨平台
可以跨主机(NFS等),便于迁移和备份
仅限本地,受宿主机文件系统影响

此外,bind类型会存在空挂载的问题。例如,上面的容器nginx-volume3在浏览器中访问时,会发现该容器无法访问Nginx的欢迎页。具体原因出现在空挂载上,如果bind类型挂载的宿主机路径为空,则会将容器内的挂载路径变为空。该特性适用于将宿主机上的配置文件替换容器内部的配置文件,也在一定程度上适用与容器文件迁移或者文件备份,但是前提条件迁移的目标地址最好是相同的宿主机系统,例如Linux系统迁移至Linux,Windows系统迁移至Windows。跨系统迁移会在一定程度上可能导致文件不能使用。

除了bind类型以外,还有一个不太常用的tmpfs类型,用于将容器内的路径指定到宿主机的内存上,通常用于一些高性能的文件读写环境下,例如将MySQL的数据库指定到内存当中,以增加缓存刷盘速度,或者用于创建一个高速写入的缓存路径。

示例如下:

docker run -d -p 8802:80 --mount type=tmpfs,destination=/app --name nginx-volume4 nginx:latest

使用docker inspect命令查看其挂载信息:

docker inspect nginx-volume4 | grep -A 11 "Mounts"

输出结果:

"Mounts": [
    {
        "Type": "tmpfs",
        "Target": "/app"
    }
],
"MaskedPaths": [
    "/proc/asound",
    "/proc/acpi",
    "/proc/kcore",
    "/proc/keys",
    "/proc/latency_stats",
    ...
],
"Mounts": [
    {
        "Type": "tmpfs",
        "Source": "",
        "Destination": "/app",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
]

通过查询挂载信息可以发现,tmpfs类型没有在宿主机上指定路径,是因为我们指定到了内存当中。

三种类型挂载的位置

三种类型其本质是,挂载的宿主机文件系统的位置不同。

四、-v与--mount参数的区别

  • -v只能挂载2种形式:bind,volume
  • --mount可以挂载3种形式:bind,volume,tmpfs

两者在功能上是等效的,但--mount更为灵活,适用于更复杂的挂载需求。使用哪种方式主要取决于具体的使用场景。如果你只需要简单的将主机上的目录挂载到容器内,-v参数足够简便;如果需要更多挂载选项,推荐使用--mount参数。

五、docker -v的四种用法

1. 不使用-v参数

示例:

docker run -d -p 8803:80 --name nginx-volume5 nginx:latest
docker inspect nginx-volume5 | grep "Mounts"

输出结果:

"Mounts": [],

当不使用-v参数时,容器也不会在宿主机上创建volume,此时当容器删除,数据也会跟随删除。

2. -v <容器内路径>

示例:

docker run -d -p 8804:80 -v /usr/share/nginx/html --name nginx-volume6 nginx:latest
docker inspect nginx-volume6 | grep -A 15 "Mounts"

输出结果:

"Mounts": [
    {
        "Type": "volume",
        "Name": "61e5198338d2fffafafe9f1bad51c67c2570506d63124c62355bc4e0e6bea5ef",
        "Source": "/var/lib/docker/volumes/61e5198338d2fffafafe9f1bad51c67c2570506d63124c62355bc4e0e6bea5ef/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
],

-v参数仅指定容器内的路径时,将创建一个匿名类型的volume,用于存储容器的数据。

3. -v <Volume 名称>:/<容器内路径>

示例:

docker run -d -p 8805:80 -v NginxVolume7_VolumeName:/usr/share/nginx/html --name nginx-volume7 nginx:latest
docker inspect nginx-volume7 | grep -A 15 "Mounts"

输出结果:

"Mounts": [
    {
        "Type": "volume",
        "Name": "NginxVolume7_VolumeName",
        "Source": "/var/lib/docker/volumes/NginxVolume7_VolumeName/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "z",
        "RW": true,
        "Propagation": ""
    }
],

-v参数指定一个不存在的volume时,在创建容器时,docker会自动创建该volume。这两种类型的-v指定挂载方式,不会存在空挂载现象。

4. -v <宿主机路径>:<容器内路径>

示例:

docker run -d -p 8806:80 -v /home/lemon/nginx_volume8_dir:/usr/share/nginx/html --name nginx-volume8 nginx:latest
docker inspect nginx-volume8 | grep -A 15 "Mounts"

输出结果:

"Mounts": [
    {
        "Type": "bind",
        "Source": "/home/lemon/nginx_volume8_dir",
        "Destination": "/usr/share/nginx/html",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
],

-v参数将宿主机的目录和容器内的目录关联起来时,默认会用宿主机的目录替换容器内部的目录数据,使用该种方式,需要注意空挂载现象。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号