目录
引言
随着容器化技术的兴起,Docker 已经成为开发、测试和部署应用程序的主流工具。Docker 的核心在于其强大的资源隔离能力,而命名空间(Namespace)是实现这一能力的关键技术之一。其中,MNT(Mount)命名空间负责隔离文件系统挂载点,为容器提供了独立的文件系统视图。
1 基础概念回顾
1.1 命名空间概述
- 命名空间是Linux内核提供的一种资源隔离机制,它允许将全局资源封装在独立的命名空间中,使得不同命名空间内的进程无法直接访问或干扰其他命名空间内的资源
- 这种隔离机制为容器提供了独立的运行环境,使得容器内的进程就像运行在一个独立的操作系统中一样
1.2 命名空间的类型
Linux 内核提供了多种类型的命名空间,每种命名空间负责隔离不同类型的资源。常见的命名空间类型包括:
- Mount Namespace(MNTNamespace):隔离文件系统挂载点
- UTS Namespace:隔离主机名和域名
- IPC Namespace:隔离进程间通信资源(如消息队列、共享内存等)
- PID Namespace:隔离进程ID
- Network Namespace:隔离网络接口、IP地址、路由表等网络资源
- User Namespace:隔离用户ID和组ID
2 MNT命名空间详解
2.1 MNT命名空间的概念
- MNT命名空间是Linux内核提供的一种用于隔离文件系统挂载点的机制
- 每个MNT命名空间都有自己独立的文件系统挂载表,包括挂载点、挂载的文件系统类型、挂载选项等信息
- 通过MNT命名空间,不同的容器可以拥有独立的文件系统视图,彼此之间互不干扰
2.2 MNT命名空间的作用
- 文件系统隔离:确保容器内的文件系统挂载点与宿主机及其他容器内的文件系统挂载点相互独立,提高系统的安全性
- 独立的文件系统视图:每个容器都可以拥有自己的文件系统视图,包括根文件系统、挂载的数据卷等,方便部署不同的应用程序
- 文件系统挂载管理:在MNT命名空间中,可以方便地进行文件系统挂载和卸载操作,而不会影响到其他命名空间
2.3 MNT命名空间的工作原理
2.3.1 MNT命名空间的创建与销毁
- 在Linux中,可以使用unshare命令或通过编程调用unshare()系统调用来创建新的MNT命名空间
- 当不再需要某个MN命名空间时,随着该命名空间内最后一个进程的退出,命名空间会自动销毁
2.3.2 MNT命名空间的挂载传播
挂载传播(Mount Propagation)决定了挂载事件在不同命名空间之间的传播方式。Linux 内核支持三种挂载传播类型:
- MS_SHARED:挂载事件会在共享的命名空间之间传播
- MS_PRIVATE:挂载事件不会在命名空间之间传播,每个命名空间都有自己独立的挂载表
- MS_SLAVE:主命名空间中的挂载事件会传播到从命名空间,但从命名空间中的挂载事件不会传播到主命名空间
在Docker中,默认情况下,容器的MNT命名空间与宿主机的MNT命名空间是私有的(MS_PRIVATE)
2.3.3 MNT命名空间的挂载点管理
在MN命名空间中,可以使用 mount和 umount命令来管理挂载点。
2.4 MNT命名空间创建与挂载管理

- 用户请求创建容器:用户通过Docker命令启动一个容器
- Docker 守护进程接收请求:Docker守护进程接收到用户的请求,开始创建容器
- 创建新的进程并设置 MNTNamespace:Docker创建一个新的进程,并为其设置独立的MNT命名空间
- 在MNT Namespace中初始化挂载表:在新的MN命名空间中初始化挂载表,准备后续的挂载操作
- 是否需要挂载数据卷:判断是否需要挂载宿主机目录作为数据卷
- 是:挂载宿主机目录到容器挂载点,并在容器内设置挂载点可见性
- 否:使用镜像层作为根文件系统
- 启动容器内进程:在容器内启动用户指定的进程
- 容器运行中:容器进入运行状态,用户可以与容器进行交互
- 用户请求卸载挂载点:用户可以通过Docker命令请求卸载某个挂载点
- 在 MNTNamespace 中卸载挂载点:在容器的 MNT命名空间中卸载指定的挂载点
- 更新挂载表:更新 MNT命名空间中的挂载表,反映卸载操作
- 容器继续运行或退出:容器继续运行或根据用户请求退出
- 容器是否退出:判断容器是否退出
- 是:销毁 MNT命名空间
- 否:回到容器运行中状态
3 MNT命名空间在Docker中的应用
3.1 Docker容器中的MNT命名空间
- 在Docker容器中,每个容器都会创建一个新的 MNT命名空间
- 容器内的文件系统操作(如挂载、卸载文件系统)都在该 MNT命名空间中进行,与宿主机及其他容器的文件系统环境相互独立
3.2 Docker镜像与MNT命名空间
- Docker镜像是容器文件系统的基础
- 当启动一个容器时,Docker会根据镜像创建一个可读写的文件系统层,并将其挂载到容器的MNT命名空间中作为根文件系统
3.3 Docker数据卷与 MNT命名空间
- Docker数据卷允许将宿主机上的目录或文件挂载到容器中
- 当使用数据卷时,Docker会在容器的 MNT命名空间中创建一个挂载点,将宿主机上的目录或文件挂载到该挂载点上
3.4 Docker容器MNT命名空间架构

- 宿主机文件系统:宿主机上的文件系统,包括各种目录和文件
- 宿主机MNT Namespace:宿主机上的默认MNT命名空间,宿主机进程在该命名空间中运行
- 宿主机进程:在宿主机上运行的进程,属于宿主机 MNT命名空间
- 容器 MNTNamespace:Docker为容器创建的独立 MNT命名空间
- 容器根文件系统层:根据Docker镜像创建的可读写文件系统层,挂载到容器的MNT命名空间中作为根文件系统
- 容器数据卷挂载点:在容器的MNT命名空间中创建的挂载点,用于挂载宿主机上的数据卷目录
- 宿主机数据卷目录:宿主机上用于数据卷的目录,通过挂载传播与容器数据卷挂载点关联
- 容器内进程:在容器内运行的进程,属于容器MNT命名空间,可以访问容器根文件系统层和数据卷挂载点
4 MNT命名空间的实践示例
# 创建一个宿主机目录用于数据卷
mkdir -p /data/my_lv
# 启动一个容器并挂载数据卷
docker run -it --name mnt-namespace-demo \
--mount type=bind,source=/data/my_lv,target=/container_data \
ubuntu:20.04 bash
# 在容器内查看挂载点
mount | grep container_data
# 在容器内创建文件并写入数据
echo "Hello from container!" > /container_data/hello.txt
# 退出容器
exit
# 在宿主机上查看数据卷中的文件
cat /data/my_lv/hello.txt
# 清理资源
docker stop mnt-namespace-demo
docker rm mnt-namespace-demo
# 输出示例
[root@node1 ~]# mkdir -p /data/my_lv
[root@node1 ~]# docker run -it --name mnt-namespace-demo \
> --mount type=bind,source=/data/my_lv,target=/container_data \
> ubuntu:20.04 bash
root@9d56bd4a5970:/# mount | grep container_data
/dev/mapper/centos-root on /container_data type xfs (rw,relatime,attr2,inode64,noquota)
root@9d56bd4a5970:/# echo "Hello from container!" > /container_data/hello.txt
root@9d56bd4a5970:/# exit
exit
[root@node1 ~]# cat /data/my_lv/hello.txt
Hello from container!
[root@node1 ~]# docker stop mnt-namespace-demo
docker rm mnt-namespace-demomnt-namespace-demo
[root@node1 ~]# docker rm mnt-namespace-demo
mnt-namespace-demo
[root@node1 ~]#
5 总结
- MNT命名空间作为Docker实现资源隔离的核心技术之一,为容器提供了独立的文件系统视图
- 通过MNT命名空间,Docker实现了容器内文件系统挂载点与宿主机及其他容器内文件系统挂载点的隔离,提高了系统的安全性和可靠性
- Docker的数据卷和存储驱动等功能也基于 MNT命名空间,为容器提供了灵活、高效的文件系统管理方案