首页 > 其他分享 >容器目录挂载原理

容器目录挂载原理

时间:2023-05-20 18:22:54浏览次数:56  
标签:容器 隔离 lib mount 文件系统 挂载 目录

前言

就我目前的对容器的了解, 使用namespace技术实现隔离, 使用cgroups技术实现资源限制. 但是具体是如何实现却从未深究过.

闲来无事, 挑其中的Mount Namespace来康康, 容器是如何实现目录隔离的.

目录隔离

耗子叔的这篇文章中对此技术进行了介绍.

c函数库中, 可通过如下方式实现目录的隔离:

int container_main(void* arg)
{
 // 调用 mount 方法, 触发目录隔离机制. 将根目录替换为 /root/tmp
 mount("/root/tmp", "/", "tmpfs", 0, "");
 // dosomething
 return 1;
}

void main(){
  // 调用 clone 创建子进程
	// 传递 CLONE_NEWNS 标识, 标明需要创建目录隔离
  clone(container_function, stack, CLONE_NEWNS | SIGCHLD , NULL)
}

如果想在命令行中测试目录隔离, 也可以如此操作:


# 创建用于挂载的临时目录
mkdir -p mount/bin
mkdir -p mount/lib64
mkdir -p mount/lib
# 将执行文件放进去
cp /bin/ls  mount/bin
# 将依赖的链接库放入 (依赖库可通过命令 ldd /bin/ls 查看)
cp /lib/x86_64-linux-gnu/libselinux.so.1 mount/lib
cp /lib/x86_64-linux-gnu/libc.so.6 mount/lib/
cp /lib/x86_64-linux-gnu/libpcre.so.3 mount/lib/
cp /lib/x86_64-linux-gnu/libdl.so.2 mount/lib/
cp /lib64/ld-linux-x86-64.so.2 mount/lib64/
cp /lib/x86_64-linux-gnu/libpthread.so.0 mount/lib/
# 替换运行进程的根目录
# 执行此命令时, chroot 命令会将 ls 命令的运行根目录替换为 ./mount 目录
# 可以尝试着执行 /bin/ls 命令查看
chroot ./mount /bin/ls

至此, 虽然举的例子很简单, 但依然足够我们理解目录隔离了. 容器启动后, 会将整个进程的根目录换掉, 甚至直接挂载整个操作系统的ISO. 这也就解释了为什么容器只是一个运行在宿主机上的进程, 却可以表现为不同的操作系统.

docker中, 容器和镜像的文件系统目录, 保存在宿主机的/var/lib/docker/overlay2.

你可以通过命令docker inspect <container_id>来查看容器的层级关系.

至于docker是如何将镜像的多层进行聚合, 最终展现给容器的, 简单说是通过UnionFS 技术, 将多个目录挂载到同一个目录下, 且可以设置优先级. 因为使用了union mount技术, 因此在overlay2中是看不到容器的完整文件系统的. 它实际上并没有在磁盘上创建一个包含所有层文件的单一目录。相反,当你查看容器的文件系统时,Docker 和 Linux 内核会动态地将所有层组合在一起,使它们看起来像一个单一的文件系统。因此,即使你可以在 /var/lib/docker/overlay2 下找到每个层的文件,你也不能直接在这里找到一个包含容器完整文件系统的单一目录.

虽然在overlay2目录下没有容器的完整文件系统, 但其实在宿主机的/proc/<pid>/root目录中可以看到, 不过前面也说了, 完整的文件系统是动态组合的, 因此/proc/<pid>/root目录也只是一个软连接. 至于容器的pid, 可以通过命令docker inspect --format '{{ .State.Pid }}' <container_id>获取.

exec

目录隔离使得容器启动后文件系统自成一派. 那么执行exec命令进入容器时, 又是如何做到的呢?

那必然是系统已经支持的啦. 在/proc/<pid>/ns目录下, 记录了命令空间隔离的数据.

image-20230520175409411

其中的mnt记录的就是目录隔离. 可以使用命令行nsenter -t <pid> -m来进入到特定进程的目录命名空间. (-m 表示要进入 mount namespace). 命令执行后, 再执行ls命令, 就会发现已经进入到容器的文件系统中了.

c的函数库中, 则使用setns函数来实现此功能. 函数具体使用不做赘述.


至此, 容器是如何做到目录隔离的, 有了一个大致模糊的印象. 收工.

标签:容器,隔离,lib,mount,文件系统,挂载,目录
From: https://www.cnblogs.com/hujingnb/p/17417585.html

相关文章

  • jre jdk更改目录后Java无法运行问题解决方案
    问题:在将Java文件(包含jdkjre)由C盘直接剪贴到D盘后,所有Java程序无法运行,且其Java图标不再显示。解决方案:首先更改环境变量。当我们单纯地将Java文件更改位置后,我们计算机的环境变量仍未改变,依旧是当时安装Java时的配置。步骤:控制面板—>系统和安全—>系统—>高级系统设置—>环境......
  • WSL 2 上的 Docker 容器 (1)
    ##wsl--helpwsl帮助##wsl-l-v 列出正在运行的wslPS>wsl-l-v NAME         STATE     VERSION*Ubuntu-18.04     Running    1 docker-desktop-data  Running    2 docker-desktop ......
  • linux默认目录和常用文件、目录
    1、介绍各种linux发行版本之间遵循基本一致的文件命名和使用规则,目录本身不具备特殊性,而是系统默认运行、安装、配置等会将文件保存在各个约定的目录下,建议用户也遵循这一约定,方便管理。2、默认目录(1)binbinaries二进制文件的缩写,存放的是普通命令。比如cat,cd(2)sbinsuperbin......
  • linux文件和目录命令
    1、ls单词list的缩写,列举当前目录下的文件。ls列举文件ls-a列举所有文件,包括.和..ls-l列举ls涉及文件的详细信息,可以和-a同时使用ls-S根据文件大小排序ls-t根据更新时间排序lsa*列出以a开头的文件,如果是目录,会列出目录以及目录的一级子文件lsa*w*可以同时列出......
  • linux默认目录
    1、介绍在linux中,一切皆文件,即通过对文件的操作实现不同功能。(ll命令查看)目录是文件、网络访问也是文件、硬件设备还是文件。2、文件属性(1)文件类型第一个字符表示文件类型:d对应目录、-对应文件、l对应链接文档,b表示为装置文件里面的可供储存的接口设备(可随机存取装置);c......
  • c++STL—容器map/multimap
    1、map基本概念1.1、简介map中所有元素都是pairpair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)所有元素都会根据元素的键值自动排序1.2、本质map/multimap属于关联式容器,底层结构是用二叉树实现。1.3、优点可以根据key值快速找到value值1.4、map和multimap区别map不......
  • 98.关联容器
      关联容器支持高效的关键字查找和访问。两个主要的关联容器(associative-container)类型是map和set。map中的元素是一些关键字-值(key-value)对:关键字起到索引的作用,值则表示与索引相关联的数据。set中每个元素只包含一个关键字:set支持高效的关键字查询操作---检查一个给定关键......
  • C++ 如何快速实现一个容器的迭代器
    C++如何快速实现一个容器的迭代器引言C++的标准库中的容器都会提供迭代器,如果一个容器满足forward_range,那么这个容器一般会提供以下成员类型和函数:iteratorconst_iteratorbeginendbegincend如果该容器还满足bidirectional_range,那么该容器还会额外提供以下成员类型和......
  • 详解c++STL—容器set/multiset
    1、set基本概念1.1、功能所有元素都会在插入时自动被排序1.2、本质:set/multiset属于关联式容器,底层结构是用二叉树实现。1.3、set和multiset区别set不允许容器中有重复的元素multiset允许容器中有重复的元素2、set构造和赋值2.1、功能描述创建set容器以及赋值2.1、构造set<T>st;/......
  • Docker容器安装示例(nginx、redis、nacos、oracle)
    1.nginx示例1.创建容器1.查看是否有nginx镜像dockerimages2.如果没有镜像,可以搜索镜像dockersearchnginx3.指定版本拉取nginxdockerpullnginx:1.20.04.查看镜像dockerimages5.创建容器(-d后台运行,-p容器80端口映射到宿主机8080端口,指定名称nginx-test,指定镜像ID:......