自己动手写Docker

一、简介

容器实质上是一个进程,只是被namespace进行了视图隔离以及cgroup限制了资源的使用。

所以,首先我们要使用clone系统调用创建一个进程,并且通过参数为该进程创建新的命名空间,然后再在系统的默认hierarchy下为该进程创建一组cgroup,并将该进程的pid写入进行资源限制。

镜像的实现是将镜像文件放在某个固定的目录下,然后创建好进程后,通过pivot_root系统调用将进程的根目录切换为当前目录,这样容器进程就只能访问镜像文件,而不能访问别的目录。

网络部分则主要通过虚拟网卡以及虚拟网桥来实现。

二、具体过程

  • 首先使用命令行工具,构造一个命令行,可以运行我们自定义的命令,比如 run、init、exec、stop、logs等等
  • 然后定义这些命令的实现,run命令用于运行一个容器进程,init用于初始化这个容器进程,stop用来停止容器
    • run 命令:
      • 接收用户传来的该容器要执行的具体任务,比如docker 默认是执行/bin/bash命令
      • 接收参数tty表示是否提供一个交互式的环境
      • 接收 系统资源限制以及volume的名字
      • 还有一些其他标志,例如-e,为容器进程设置环境变量,-p进行端口映射
      • 通过 -name提取到容器名字
      • 创建一个启动新的线程的命令,该命令/proc/self/exe,通过管道传入参数init,相当于子进程执行的是父进程的程序,即还是一个命令行工具,只是这次命令改为了init,而不是run,执行初始化操作(该子进程就相当于容器进程,不过此时只是创建出这么一段逻辑来,但还未执行)。
      • 创建一个工作空间,包括一个读写层的文件夹和一个只读的文件夹(镜像文件),通过aufs的形式挂载到特定的目录下。
      • 将容器信息持久化到特定的文件夹下,为exec、stop等命令提供信息
      • 执行创建子进程的命令,去创建好的工作空间去工作,此时子进程阻塞到读取用户传入的命令参数上。
      • 父进程创建cgroup,此时子进程还未执行init命令,所以可以通过当前子进程的mount信息,找到subsystem的信息,创建线程组,并将子进程pid写入进行资源限制。
      • 如果网络信息不为空,将容器加入网络
      • 然后父进程通过管道发送用户要容器执行的命令,子进程接收到,开始init操作
      • 如果是交互式的,则父进程此时开始阻塞等待子进程,等待子进程运行结束后,回收资源,然后执行结束退出,如果不是交互式,而是后台运行的容器,则父进程不阻塞执行运行完毕退出,只留下子进程,然后托管给OS的init进程。
    • init 命令:
      • 首先从管道读取到用户要执行的命令
      • 将子进程的工作目录改为工作空间的路径,工作空间的作用是切换这个子进程的根文件系统:通过mount --bind . .的方式将自己在新创建的属于自己的mount namespace中的根文件目录改变为自己,此时mount namespace真正的生效,此时子进程只能看到自己当前路径下的资源,然后通过pivot_root系统调用将子进程的根文件目录改变为镜像,前面自己绑定自己,是为了防止子进程的根文件系统是linux的根文件系统的话,使用这个系统调用,会导致整个linux系统的根文件系统替换为镜像,这样别的进程就无法工作了。所以,先替换子进程的根文件系统为自己当前所在的路径,然后再将根文件系统替换为镜像,这样只是当前目录的文件被替换掉了。
      • 挂载/proc、/tmpfs等内存文件系统
      • 替换路径为"/"
      • 然后通过找到用户传来的命令的全路径,通过系统调用,将子进程堆栈中的信息替换掉,例如代码段的内容替换为用户要执行的命令,这样子进程就会执行用户要执行的命令了。
    • stop命令:通过系统调用向进程发送信号,使其阻塞

参考

https://blog.csdn.net/qq_27068845/article/details/90705925

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值