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究竟有什么区别?的更多相关文章
- Data Volume 之 bind mount - 每天5分钟玩转 Docker 容器技术(39)
storage driver 和 data volume 是容器存放数据的两种方式,上一节我们学习了 storage driver,本节开始讨论 Data Volume. Data Volume 本质 ...
- 37-Data Volume 之 bind mount
storage driver 和 data volume 是容器存放数据的两种方式,上一节我们学习了 storage driver,本节开始讨论 Data Volume. Data Volume 本质 ...
- 第 6 章 存储 - 039 - Data Volume 之 bind mount
Data Volume Data Volume 本质上是 Docker Host 文件系统中的目录或文件,能够直接被 mount 到容器的文件系统中. Data Volume 有以下特点: 1.Dat ...
- 039、Data Volume 之 bind mount (2019-02-28 周四)
参考https://www.cnblogs.com/CloudMan6/p/7142150.html Date Volume 本质上是Dokcer host文件系统中的目录或者文件,能够直接被 ...
- 将数据挂载到 docker 容器中的3种方式:volume、bind mount、tmpfs
出处:https://deepzz.com/post/the-docker-volumes-basic.html
- docker managed volume - 每天5分钟玩转 Docker 容器技术(40)
docker managed volume 与 bind mount 在使用上的最大区别是不需要指定 mount 源,指明 mount point 就行了.还是以 httpd 容器为例: 我们通过 - ...
- 040、Docker managed volume(2019-03-01 周五)
参考https://www.cnblogs.com/CloudMan6/p/7152775.html docker managed volume 与bind mount 在使用上最大的区别是不需要 ...
- 第 6 章 存储 - 040 - docker managed volume
docker managed volume 与 bind mount 在最大区别是不需要指定 mount 源,指明 mount point 就行了 通过 -v 告诉 docker 需要一个 data ...
- [转帖]Docker的数据管理(volume/bind mount/tmpfs)
Docker(十五)-Docker的数据管理(volume/bind mount/tmpfs) https://www.cnblogs.com/zhuochong/p/10069719.html do ...
随机推荐
- Puppeteer学习笔记 (2)- Puppeteer的安装
本文链接:https://www.cnblogs.com/hchengmx/p/11009849.html 1. node的下载安装 由于puppeteer是nodejs的一个库,所以首先需要安装no ...
- alertmanager集群莫名发送resolve消息的问题探究
alertmanager集群莫名发送resolve消息的问题探究 术语 告警消息:指一条告警 告警恢复消息:指一条告警恢复 告警信息:指告警相关的内容,包括告警消息和告警恢复消息 问题描述 最近遇到了 ...
- spring boot用ide新建项目遇到的restcontroller不能导入的问题
才开始学习spring boot,第一个程序helloworld就碰到@RestController和@RequestMapping(/hello)的注解都会报错的问题. 我个人的解决方法: 1.sp ...
- 写了个基于 MacOS + iTerm2 自动打开窗口执行命令的工具
大家好,我是秋风,今天要给大家带来的这个工具是我最近写的 一个 npm 工具.mmt 是基于 MacOS + iTerm2 ,目的主要是为了提高日常生活中的效率,接下来我带大家看看一些常用的一些场景. ...
- SAP 实例 13 Random Grouping with LOOP
REPORT demo_loop_group_by_random. CLASS demo DEFINITION. PUBLIC SECTION. CLASS-METHODS: main, class_ ...
- SAP BOM 读取
1.查找 物料号.工厂.物料描述. 表:MARA MARC MAKT 逻辑: 输入物料(选择选项)中的物料编号(MARA-MATNR)和 输入工厂(选择选项 ...
- mysql中innodb和myisam区别
前言 InnoDB和MyISAM是很多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,5.7之后就不一样了. 1.事务和外键 ● InnoDB具有事务,支持4个事务隔离级别,回滚,崩溃修 ...
- 用 PyQt5 快速构建一个简单的 GUI 应用
1. 介绍 Python GUI 常用的 3 种框架是:Tkinter.wxpython.PyQt5 PyQt5 基于 Qt,是 Python 和 Qt 的结合体,可以用 Python 语言编写跨平台 ...
- 干货 |《2022B2B新增长系列之企服行业橙皮书》重磅发布
企服行业面临的宏观环境和微观环境已然发生了明显的变化.一方面,消费级互联网成为过去式,爆发式增长的时代结束.资本.媒体的目光已经悄然聚焦到以企服行业所代表的产品互联网身上,B2B企业正稳步走向C位. ...
- 透过Redis源码探究Hash表的实现
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/667 本文使用的Redis 5.0源码 概述 我们在学习 Redis ...