Docker Volume原理

发布时间 2023-07-21 08:40:08作者: 王景迁

挂载命令

把宿主机/home目录挂载到容器的/test目录当中。
docker run -v /home:/test ...

挂载操作不破坏隔离性

在rootfs准备好(联合挂载)之后,在执行chroot之前,把Volume指定的宿主机目录挂载到指定的容器目录。
执行这个挂载操作时,容器init进程已经创建(负责完成根目录的准备、挂载设备和目录、配置 hostname等初始化操作),Mount Namespace已经开启。宿主机上看不见这个挂载点,保证了容器的隔离性不会被Volume打破。

绑定挂载原理

Linux的绑定挂载(bind mount)的主要作用就是,把一个目录或者文件,而不是整个设备,挂载到一个指定的目录上。在该挂载点上执行的任何操作只针对被挂载的目录或者文件有效,原挂载点的内容会被隐藏起来且不受影响。绑定挂载是一个inode(存放文件内容的对象)替换的过程。dentry,也叫目录项,是访问这个inode的指针。

mount --bind /home /test,会将/home挂载到/test上,相当于将/test的dentry重定向到了/home的inode。当修改/test目录时,实际修改的是/home目录的inode。一旦执行umount命令,/test目录原先的内容就会恢复,因为修改真正发生在的是/home目录。

$ docker run -d -v /home:/test nginx:latest

在容器的Volume里创建一个文件a
$ docker exec -it ff694a3e9b sh
$ cd /test
$ touch a

文件a已经出现在了宿主机的/home目录上
$ ls /home
a

在宿主机上查看该容器的可读写层,/test目录内容是空的。
$ ls /var/lib/docker/overlay2/698112b0af00028a866741e78735a59c5b0b63ac0bc0196bb3a409f3ceb9a0e1/diff/test
容器Volume里的信息不会被docker commit提交掉。但这个挂载点目录/test本身会出现在新的镜像当中。因为新建目录操作,不是挂载操作,Mount Namespace无法隔离。

参考资料

《深入剖析Kubernetes》