Silentdoer

导航

docker使用的核心技术

1.cgroup,这个用来限制cpu和内存;(通过改配置文件,让pid的cpu和内存限制在配置文件里指定的大小)

 

2.namespace,这个用来隔离进程/文件系统等等;(unshare -m -u /bin/bash,那么当前session就是在一个namespace里了,在这里修改hostname和加载iso文件,是不会影响宿主机的;注意:不止有-m -u还有其他隔离参数)

具体行为:在执行了unshare -m -u /bin/bash的session a里执行hostname可以看到此时的hostname是aaa(此时可以开启另外一个控制台即新的session b),在session a里执行hostname ns1即在隔离里修改hostname,然后执行hostname可以看到session a里确实改成了ns1,此时切换到session b可以看到session b即宿主机里hostname是没有修改为ns1的;(已经测试过不开启隔离修改hostname是会同时影响其他宿主机session)

第二个行为是:mount 1.iso /var/docker/app1_single_write_folder/iso1folder,然后mount |grep iso1folder可以看到挂载了,但是在宿主机session里是看不到的;

 

3.chroot,用于容器应用的根目录是隔离后的文件系统目录;

这里app1_single_write_folder如果里面是/bin,/lib,/opt这样的结构,则可以chroot到这个目录,实现docker应用真正和宿主机的文件系统隔离

,它应该是在开启隔离后再执行的,而cgroup是改的app1_single_write_folder里面的配置;chroot后就可以执行应用了;

 

4.overlay2,层叠文件,用于将多个目录“合并”为一个目录,使得一个容器应用的部分资源是可以复用的;

mount -t overlay overlay -o lowerdir=/var/docker/readonly1:/var/docker/readonly2,upperdir=/var/docker/app1_single_write_folder,workdir=/var/docker/app1_single_tmp_folder /var/docker/app1_overlay_merged_folder

最终在宿主机或namespace里mount|grep app1_overlay_merged_folder看到有个加载好的层叠目录,cd到app1_overlay_merged_folder(之前是空白目录,app1_single_tmp_folder工作目录也是空白目录),可以看到它是由只读目录和可写目录堆叠后的目录,往app1_overlay_merged_folder写数据最终是写到了app1_single_write_folder里;

流程是:在宿主机session里先创建一个overlay,即最终是app1_overlay_merged_folder,然后由于app1_single_write_folder里有volume_bbb

这个时候仍然是在宿主机session里执行:mount --bind /var/host/volume_aaa /var/docker/app1_overlay_merged_folder/volume_bbb,注意这里是用的overlay的而非writedir里的,5里是writedir目录

然后再通过unshare -m -u /bin/bash开启隔离,最终是这个顺序;

app1_single_write_folder是应用真正的数据目录,但是app1_overlay_merged_folder这个也算(但本质上是空目录,但umount后),因为开启overlay是在宿主机的session里;

5.mount --bind(VOLUME),容器可以挂载外部的文件系统,实现和宿主机文件系统交互。(这个有点忘了,应该是在开启namespace之前先将容器目录即写目录里的某个目录如aaa, aaa bind到宿主机里的其他目录上如/var/kkk,当开启namespace后以及overlay2后,往该aaa目录里写数据,最终在宿主机里/var/kkk里能看到这个数据)

具体是这样:在没有通过unshare开启mount隔离之前,先执行:

mount --bind /var/host/volume_aaa /var/docker/app1_single_write_folder/volume_bbb,然后在宿主机里mount|grep volume_bbb是可以看到的;

然后执行:unshare -m -u /bin/bash后开启了session a,在此session里用mount|grep volume_bbb也一样可以看到这个挂载;

然后在session a里往volume_bbb里写文件,在volume_aaa里可以看到(不管是在session a还是宿主机的),同样的在宿主机的session往volume_aaa里写了文件,在session a里查看volume_bbb也可以看到这个文件,这样就实现了Docker的VOLUME 隔离里访问宿主机的目录文件的效果;

【注意,按这个顺序mount --bind的挂载项,虽然宿主机和session a里都能看到,但是在session a里取消挂载是不会影响宿主机里的,而且退出session a后重新进入session a可以发现又自动挂载了】

 

6.还有个就是chroot后执行程序前可能会设置LD_LIBRARY_PATH和添加PATH

 

7.用户这块docker用的是一个ocpuser:1001的账户,它在宿主机里的/etc/passwd里是找不到的,在chroot后的/etc/passwd里是能看到的;

而docker exec -it $containerId /bin/bash的实现原理则是通过命令nsenter,比如在宿主机里执行nsenter --target $pid -m -u -i /bin/bash,然后进去后在su ocpuser

,经过测试这里的/bin/bash可以不要,然后可以实现直接进入namespace就自动切换用户而不需要再次执行命令来切换,具体为:nsenter --target $pid -m -p -i su - ocpuser

 

8.docker chroot后的home目录~不一定是/home/xxx里,还可以是/opt这样的目录,具体在/etc/passwd里相关账户里有配置。

 

(似乎不是用的这个)还用到了伪终端技术(pty),实现在宿主机上进入容器里执行命令(错误,docker用到的是nsenter命令实现的在宿主机里开启一个bash并连接到已经存在的namespace里)

 

N.整体流程:

一.先修改app1_single_write_folder目录里的sys/fs/cgroup/...里的相关内存和cpu限制配置,为后续执行应用时的限制做好准备;

二.在宿主机session里创建overlay挂载目录app1_overlay_merged_folder

三.如果Dockerfile里有VOLUME,则将挂载overlay目录app1_overlay_merged_folder里的某个子目录(这个子目录真正是在app1_single_write_folder里的,但是要通过overlay目录挂载)挂载到宿主机其他目录里

四.再通过unshare -m -u /bin/bash开启namespace隔离;【也可能是先chroot再开启隔离;问了chatgpt,应该是最后chroot】

五.然后chroot到app1_overlay_merged_folder里,此时/sys/fs/cgroup就是之前app1_single_write_folder/sys/fs/cgroup;

六.然后在新的root环境执行应用;

 

如果要实现和宿主机共用/bin,/lib等目录,可以在最后的lowerdir里创建空的lib,bin等目录

等挂载了overlay后,再通过:(不行,基本上就几个思路mount --bind,ln -s,多层overlay试了都不行,而又无法将/作为lowerdir,只能复制一份?)

sudo mount --bind /bin /home/silentdoer/DockerStudy/app1_overlay_empty_folder/bin
sudo mount --bind /lib /home/silentdoer/DockerStudy/app1_overlay_empty_folder/lib
sudo mount --bind /lib64 /home/silentdoer/DockerStudy/app1_overlay_empty_folder/lib64

来将系统的这些目录挂载到overlay目录上;【但是有问题,因为这个其实就是VOLUME的方式,这个会导致容器里的程序可以修改宿主机的/bin目录

,而如果是以只读方式挂载,则也有问题,会导致容器无法往/lib里写自己的特有的依赖;但是如果是完全的堆叠则可以,即lowerdir里就是保存有lib,bin等目录且

里面有需要的文件而非软连接或者堆叠目录,到最后overlay里bin显示的是lowerdir和upperdir堆叠后的,upperdir里的会“覆盖”lowerdir里的,这样就能实现】

这里最大的两个问题是,一个是无法以根目录作为lowerdir,第二个是这个堆叠目录无法多个overlay目录进行叠加,比如lowerdir里的某个目录自己也是overlay的目录

,最终是不会叠加的。】

posted on 2023-08-21 18:12  Silentdoer  阅读(24)  评论(0编辑  收藏  举报