Docker(3)Volume与绑定挂载(bind mount)机制

本文探讨了Docker如何通过mount namespace和rootfs实现文件系统隔离,并详细解析了Volume与绑定挂载(bind mount)机制。内容包括问题背景、使用方式以及原理,特别是解释了如何在容器启动前将宿主机目录挂载到容器内,以实现文件交互,同时保证容器的隔离性。最后,简要介绍了Linux的绑定挂载机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 问题背景

Docker项目使用了mount namespace和rootfs的文件镜像来实现了容器镜像文件系统和宿主机系统的隔离。但是,以下两个容器和宿主机的文件交互问题怎么解决?

  • 容器中新建的文件,宿主机怎么获取到?
  • 宿主机上的文件和目录,容器内部进程怎么获取?

2. 使用方式

可以通过以下两种起Docker容器的方式,把宿主机目录挂载进入容器的对应目录:

$ docker run -v /docker_dir ...
$ docker run -v /home:/docker_dir ...

当不指明宿主机目录时,Docker会默认在宿主机上创建一个临时目录: /var/lib/docker/volumes/[VOLUME_ID]/_data作为宿主机上的被挂载目录。

3. 原理

3.1 Docker容器原理

回忆《Docker(2)容器技术基本概念理解》中的Docker容器的核心原理:

  • 启动Linux Namespace配置
  • 设置指定的Cgroups参数
  • 切换进程的根目录(change root, 配合namespace mount)
    而在第三步执行chroot和pivot_root之前,容器进程是可以一直看到宿主机上的整个文件系统的。所以可以在这里做点文章。

3.2 绑定挂载(bind mount)机制

当我们宿主机上已经存在了一个容器镜像时,镜像的各个层,都被保存在/var/lib/docker/aufs/diff目录下,容器启动之后,会被联合挂载在/var/lib/docker/aufs/mnt下,这时候容器所需要的rootfs就准备好了。
因此,对于 2. 使用方式 中的场景,我们只需要在rootfs准备好,chroot执行之前,吧Volume指定的宿主机目录(比如/home目录),挂载到指定的容器目录(如/test目录)在宿主机上对应的目录(/var/lib/docker/aufs/mnt/[可读可写层ID]/test)上,这个Volume挂载工作就完成了。
同时,因为执行挂载时,“容器进程”已经完成了创建,所以这时Mount Namespace已经开启,所以这个挂载点,只能在容器中看见,宿主机是看不到的。保证了容器的隔离性不会被Volume打破
上面提到的挂载操作,使用的就是Linux的绑定挂载(bind mount)机制。

绑定挂载
允许用户将一个目录或者文件,挂载到一个指定的目录上,并且,之后在这个挂载点上的操作,只发生在被挂载的目录或者文件上,而原来挂载点的内容会被隐藏起来不受影响。

该去学习一下Linux内核了
绑定挂载其实是一个inode替换的过程,在Linux操作系统中,inode可以理解为存放文件内容的对象,而dentry,也叫目录项,就是访问这个inode所使用的“指针”。
在下图中,mount --bind /home /test ,会把/home挂载到/test上,实际上相当于吧/test的/dentry,指向修改为/home的inode,这样修改/test,实际上修改的是/home对应的inode。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值