我的编程空间,编程开发者的网络收藏夹
学习永远不晚

docker中的volume和bind mount区别讲解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

docker中的volume和bind mount区别讲解

不知道你在使用docker的时候,有没有注意到 volume mount和bind mount的使用? 进一步说,他们之间的区别到底是什么?

接下来的内容,我们就为你揭开他们的神秘面纱。

相同之处

首先,说相同之处:

volume和bind mount都是持久化容器的机制。

不同之处

再来说说,他们的不同之处:

volume是由docker来进行管理的,而bind mount完全是依赖于主机的目录结构和操作系统

volume 相对于 bind mount的 优点

  • volume更加容易进行备份和迁移
  • 可以通过docker客户端命令或者docker api来管理volume (比如:docker volume命令)
  • volume可以在linux和windows容器中运行
  • volume可以更加安全的在多个容器之间进行共享
  • volume驱动程序允许在远程主机或云提供商上存储卷,以加密volume的内容或添加其他功能
  • 新volume的内容可以由容器预先填充
  • Docker Desktop上的卷比Mac和Windows主机上的绑定挂载具有更高的性能。

此外,与将数据持久化到容器的可写层相比,volume通常是更好的选择,因为volume不会增加使用它的容器的大小,而且volume的内容存在于给定容器的生命周期之外。

也就是说,当容器被移除了之后,volume中的内容还是可以独立存在的。

下图演示了volume和bind mount,以及和容器之间的关系图:

我们可以看到:

  • volume是可docker的存储区域相关的
  • bind mount是直接和操作系统相关的

下面,我们分别展示,volume的挂载、使用的一些操作

volume操作

创建容器,使用volume

我们可以通过下面的命令创建一个容器,使用volume

docker run -d \
  --name devtest \
  -v myvol2:/app \
  nginx:latest

其中:-v选项,后面的第一个参数myvol2就是volume的名字,如果在容器使用volume时,volume不存在,那么会自动创建这个volume

[root@centos7 ~]# docker volume ls
DRIVER    VOLUME NAME
local     myvol2
[root@centos7 ~]#

可以查看该volume在docker 宿主机上的具体的路径

[root@centos7 ~]# docker volume inspect myvol2
[
    {
        "CreatedAt": "2022-08-23T22:04:20-04:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/myvol2/_data",
        "Name": "myvol2",
        "Options": null,
        "Scope": "local"
    }
]
[root@centos7 ~]#

Mountpoint就指明了这个volume在文件系统上的具体位置。

容器通过:-v myvol2:/app 将volume挂载到容器的/app目录中

[root@centos7 ~]# docker exec -it devtest df -h
Filesystem               Size  Used Avail Use% Mounted on
overlay                   50G  3.0G   48G   6% /
tmpfs                     64M     0   64M   0% /dev
tmpfs                    1.4G     0  1.4G   0% /sys/fs/cgroup
shm                       64M     0   64M   0% /dev/shm
/dev/mapper/centos-root   50G  3.0G   48G   6% /app
tmpfs                    1.4G     0  1.4G   0% /proc/asound
tmpfs                    1.4G     0  1.4G   0% /proc/acpi
tmpfs                    1.4G     0  1.4G   0% /proc/scsi
tmpfs                    1.4G     0  1.4G   0% /sys/firmware
[root@centos7 ~]#

向/app目录写文件:

docker exec -it devtest bash -c "echo test > /app/myfile.test"

查看卷中的文件是否已经被创建

[root@centos7 ~]# cd /var/lib/docker/volumes/myvol2/_data
[root@centos7 _data]# ls
myfile.test
[root@centos7 _data]# cat myfile.test 
test
[root@centos7 _data]#

没错,确实这个文件就是写到了这个目录中了。

注意:这个volume的内容写的过程是由docker来进行管理的。

查看容器中mount信息

docker inspect devtest
        "Mounts": [
            {
                "Type": "volume",
                "Name": "myvol2",
                "Source": "/var/lib/docker/volumes/myvol2/_data",
                "Destination": "/app",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ]

可以看到Mounts部分的信息:

  • Type: volume
  • Source:就是在宿主机上的具体的目录位置
  • Destination: 容器中的挂载路径
  • Driver: volume的驱动程序类型
  • RW: 是否是读写模式

停止容器、移除容器

docker stop devtest
docker rm devtest

容器移除后,volume是否还存在吗?

[root@centos7 _data]# docker volume ls
DRIVER    VOLUME NAME
local     myvol2
[root@centos7 _data]# ls
myfile.test
[root@centos7 _data]# cat myfile.test 
test
[root@centos7 _data]#

和你想的一模一样,volume还在,其中的写入的内容,仍然存在

移除volume

docker volume rm  myvol2

注意!

移除容器和移除volume是2个独立的操作。

使用容器填充volume

另外一个 非常重要的点 :如果将volume挂载到目录中,如果目录中原来就是有文件或子目录的,那么挂载之后,会将内容拷贝到卷中来。

啥意思?

比如,我们有个镜像,在/app目录下有个a.log文件

[root@centos7 test-volume]# ls
a.log  Dockerfile
[root@centos7 test-volume]# cat a.log 
123456
12345
[root@centos7 test-volume]# cat Dockerfile 
from nginx:latest
RUN mkdir /app
copy a.log /app/a.log
[root@centos7 test-volume]#
# 构建镜像
docker build -t vol:2 .

挂载数据卷

docker run -d   --name=vo3   -v nginx-vo3:/app   vol:2

发现容器运行后,/app目录下的文件,被拷贝到volume中

[root@centos7 test-volume]# cd /var/lib/docker/volumes/nginx-vo3/_data
[root@centos7 _data]# ls
a.log
[root@centos7 _data]# cat a.log 
123456
12345
[root@centos7 _data]#

而没有,覆盖!这个点,十分的有意思!之前肯定你没有关注过!

以只读方式挂载volume

如何以只读的方式挂载volume,方法非常的简单:

只需要加上ro选项即可

-v nginx-vol:/usr/share/nginx/html:ro

示例:

docker run -d \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html:ro \
  nginx:latest

查看容器的Mounts部分的信息

docker inspect nginxtest
"Mounts": [
            {
                "Type": "volume",
                "Name": "nginx-vol",
                "Source": "/var/lib/docker/volumes/nginx-vol/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode": "ro",
                "RW": false,
                "Propagation": ""
            }
        ]

发现:"RW": false,也就是,非Read-Write的模式

试试向其中写入文件:

[root@centos7 ~]# docker exec -it nginxtest bash -c "echo 1234 > /usr/share/nginx/html/1.log "
bash: line 1: /usr/share/nginx/html/1.log: Read-only file system
[root@centos7 ~]#

和你猜的一样,会提示:只读文件系统。

OK,OK,说完了volume的原理,相关的操作,接下来,要看的就是bind mount

bind mount

使用bind mount时,将宿主机上的文件或者目录挂载到容器上。文件或者目录在主机上,是以绝对路径的方式来使用。

相比之下,当使用volume时,在主机上的Docker存储目录中创建一个新目录,由Docker管理该目录的内容。

要挂载的文件或目录不需要在Docker主机上已经存在。如果它还不存在,则按需创建它。bind mount的性能非常好,但是它们依赖于主机的文件系统具有特定的目录结构。

建议:如果你正在开发新的Docker应用程序,请考虑使用命名的volume。因为,对于bind mount来说,你不能使用Docker CLI命令来直接管理。

使用bind mount启动容器

使用以下得命令,将一个容器通过bind 挂载的方式,将宿主机的目录,挂载到容器中

docker run -d \
  -it \
  --name devtest \
  -v "$(pwd)"/target:/app \
  nginx:latest

查看容器的bind挂载情况

docker inspect devtest
"Mounts": [
            {
                "Type": "bind",
                "Source": "/tmp/source/target/target",
                "Destination": "/app",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ]

可以看到

  • Type : 挂载的类型是bind
  • source: 宿主机上的目录,当然这里使用$(pwd)变量来获取当前的工作目录

关闭、删除容器

docker container stop devtest
 docker container rm devtest

OK,接下来的这个点,非常的关键,如果绑定挂载到容器中的一个非空的目录会如何?

绑定到容器的非空目录

nginx镜像中/usr/share/nginx/html是非空的,有登录页

docker run -d \
  -it \
  --name non-empty \
  -v /tmp/soure/base:/usr/share/nginx/html \
  nginx:latest  
[root@centos7 base]# docker exec -it non-empty ls /usr/share/nginx/html
[root@centos7 base]#

发现,挂载了之后,是空的,也就是把镜像中的内容给覆盖了。

这个和volume是一个巨大的区别! 注意 !

总结

OK,我们这里总结一下,让你更好的理解voLume 和 bind 类型的挂载的区别:

  • 管理方式,volume由docker管理,docker客户端命令可操作,bind挂载不行
  • 容器中有内容的目录,volume会复制,bind mount直接将容器中的内容覆盖
  • bind mount可以设置 bind 传播参数。
  • volume可以设置驱动程序

后面的文章中,会带你看看,如何安装volume驱动,来创建特定类型的volume,实现多个节点间的数据共享······

到此这篇关于docker的volume和bind mount区别介绍的文章就介绍到这了,更多相关docker volume和bind mount内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

docker中的volume和bind mount区别讲解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Dockerfile中VOLUME与docker -v的区别是什么

这篇文章主要介绍Dockerfile中VOLUME与docker -v的区别是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Dockerfile 中的 VOLUME 挂载与 docker -v 命令挂载,两者有明
2023-06-14

Shell中exit和return的区别讲解

1.exit命令 exit命令是Shell内建命令,用于退出当前Shell进程。使用格式如下:exit []可以指定退出状态n,n的取值范围是0-255,一般情况下,0表示正常退出,非零表示异常退出。如果状态码是0-255之外的数值,
2022-06-04

vue3 中ref和reactive的区别讲解

如果在template里使用的是ref类型的数据, 那么Vue会自动帮我们添加.value,如果在template里使用的是reactive类型的数据, 那么Vue不会自动帮我们添加.value,这篇文章主要介绍了vue3 中ref和reactive的区别,需要的朋友可以参考下
2022-12-19

JS中forEach()和map()的区别讲解

forEach()和map()是JavaScript中处理数组的两个内置函数。forEach()用于遍历数组中的每个元素,并对其执行一个函数,而不需要返回值。map()遍历数组中的每个元素,并将它们映射到一个新数组中,返回包含新映射元素的新数组。forEach()常用于对数组元素进行副作用操作,例如打印或修改,而map()常用于创建数组的副本或转换数组中的元素。
JS中forEach()和map()的区别讲解
2024-04-02

golang中new与make的区别讲解

new只能开辟单个空间,不能为引用类型开辟多个空间,并且new是对类型进行内存的开辟,返回一个指向该内存空间的指针类型,如果使用new去初始化引用数据类型,不是很合适(当然,new一个对象还是可以的),因此就需要用到另一个内置函数make,需要的朋友可以参考下
2023-01-12

由浅入深讲解vue2和vue3的区别

最近发现很多要求Vue3的技术了,不得不说it技术的更新真的太快了,作为vue2老用户,我们在学习Vue3前应该了解他们的区别以及背后的原因,下面这篇文章主要给大家介绍了关于vue2和vue3区别的相关资料,需要的朋友可以参考下
2023-02-08

JS中call(),apply(),bind()函数的区别与用法详解

这篇文章主要介绍了JS中call(),apply(),bind()函数的高级用法详解,需要的朋友可以参考下
2022-12-10

Python中列表遍历使用range和enumerate的区别讲解

这篇文章主要介绍了Python中列表遍历使用range和enumerate的区别,在Python编程语言中,遍历list有range和enumerate方法,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2022-12-26

编程热搜

目录