【mydocker】容器的进阶[ 4 ]

1.docker的后台运行(detach功能)

原理:在 Docker 早期版本,所有的容器 init 进程都是从 docker daemon 这个进程 fork 出来的,这也就会导致一个众所周知的问题,如果 docker daemon 挂掉,那么所有的容器都会宕掉,这给升级 docker daemon 带来很大的风险。父子进程是异步的。创建子进程的父进程挂掉会造成子进程成为孤儿进程,进程号为1的init进程接管,实际上还是可以运行的,但是 docker daemon 挂了会导致他维护的一些资源也没了,所以容器实际上是不能正常运行的
后来docker使用了containerd-shim进程负责管理容器的创建运行停止。每个进程都有init进程(containerd-shim),containerd-shim 进程负责接收来自 containerd 的命令,启动容器中的进程,并监控它们的生命周期。

在这里插入图片描述

  • 在容器的runcommand中加入Args参数:d表示后台运行
  • 只有注意不可以一边要交互式伪终端,一边要后台运行
    • parent.Wait() 主要是用于父进程等待子进程结束,这在交互式创建容器的步骤里面是没问题的,但是指定了 -d要后台运行就不能再去等待,创建容器之后,父进程直接退出即可

2.实现docker的ps命令

思路:在容器启动后,将容器的信息存储在/var/lib/mydocker/containers/{containerID}/containner.json文件中,在执行-ps命令时,查询启动/var/lib/mydocker/containers/文件下的所有文件即可。
实现

  • 准备:
    • 1.在fork出子进程,创建container.Info实例:{name,PID,Command,create_time,status}
    • 2.创建文件夹:MkdirAll/var/lib/mydocker/containers/{%s(containerID)}
    • 3.创建文件:file := os.Create(dir,config.json),写入文件:file.WriteString(jsonstr)
    • 4.在进程停止的时候删除文件既可os.removeAll(dir)/var/lib/mydocker/containers/{containerID}
  • ps命令:
    • Files := os.ReadDir读取/var/lib/mydocker/containers文件夹的所有文件
    • 读取文件
      • dir := /var/lib/mydocker/containers+file.name
      • realPath := path.Join(dir,config.json)
      • os.Readfile(realPath)
    • json的反序列化为对象->添加到container.info切片中
    • tabwriter 是引用的text/tabwriter类库,用于在控制台打印对齐的表格,打印容器信息
      效果:
      在这里插入图片描述

3.实现mydocker的logs功能

流程
将进程的输出重定向到容器的日志文件
实现logcommand命令
实现
在这里插入图片描述

在这里插入图片描述

效果:

  • 输入:

sudo ./myDocker logs 8287657315

在这里插入图片描述

4.实现exec进入容器

原理
将当前进程的PID加入到容器的namespace中即可实现交互式访问容器,linux操作系统的setns调用即可实现。
难点
setns系统调用允许进程加入(或重新进入)到指定的 Namespace 中。由于 Namespace 涉及到整个进程的资源隔离,因此需要在进程的上下文中执行,以确保进程及其所有线程都在相同的 Namespace 中;Go Runtime 是多线程的,这意味着 Go 程序通常会有多个线程在同时运行。这种多线程模型与 ==setns 调用所需的单线程上下文不兼容。
Goroutine 会随机在底层 OS 线程之间切换,而不是固定在某个线程,因此在 Go 中执行 setns 不能准确的知道是操作到哪个线程了,结果是不确定的,因此需要特殊处理。
****:
是 C 语言可以通过 gcc 的 扩展 attribute((constructor)) 来实现程序启动前执行特定代码,因此 Go 就可以通过 cgo 嵌入 这样的一段 C 代码来完成 runtime 启动前执行特定的 C 代码
实现
在这里插入图片描述

cgo这里主要使用了构造函数,然后导入了 C 模块,
execCommand:
获得进程PID\comArray命令,通过设置环境变量,用于与C传递
fork进程
效果在这里插入图片描述

5.实现docker容器的停止

实质:停止容器的实质就是杀死容器进程。
原理:查找到容器的json文件存储地址,获得PID,使用System.kill杀死进程,修改文件的内容,statu与pid使得ps命令能够获取最新的状态。
流程
添加stopCommand-> getContainerInfoById(containerID)-> syscall.Kill(PID, syscall.SIGTERM)->json序列化-> 写入f.Write(newContentByte)
效果
在这里插入图片描述

6.实现docker的删除容器容器指令

实质:删除容器的文件夹
原理:查找到容器的json文件存储地址,获得容器状态,如果状态是停止的,直接删除文件夹;若是运行的则先停止运行再删除,如果是其他则报错即可
效果
在这里插入图片描述

正在运行的容器加上-f强制删除指令即可删除,否则报错
在这里插入图片描述

7.重构:实现容器间 rootfs 隔离

引入必要性overlayfs 实现了容器和宿主机的 rootfs 隔离,但是多个容器还是共用的一个rootfs–/root/merged ,多容器之间会互相影响。
实现:这三处调整实际上都是对宿主机上容器 rootfs 目录的调整,把 rootfs 从原来的 /root/merged 调整为/var/lib/mydocker/overlay2/{containerID}/merged ,这样实现容器之间的隔离。

  • 修改 mydocker commit 命令,实现对不同容器进行打包镜像的功能。压缩路径为imageName.tar

  • 修改 mydocker run 命令,用户可以指定不同镜像,并为每个容器分配单独的隔离文件系统

    • 根据镜像名称找到对应 tar 文件,解压后作为overlay 中的 lower 目录进行挂载
    • rootfs具有很大的修改
  • 修改 mydocker rm 命令,删除容器时顺带删除文件系统
    效果

  •   1.运行容器,容器的/tmp中写入a.txt
    

    在这里插入图片描述

  •   2.将容器打包为b.tar新镜像
    

    在这里插入图片描述

  •   3.在b镜像创造的容器中可以看到a.txt
    

    在这里插入图片描述

8.实现docker容器环境变量传递

实现:mydocker run -e flag,支持在启动容器时指定环境变量,让容器内运行的程序可以使用外部传递的环境变量
原理
在构建 cmd 的时候指定 Env 参数。

  • 1)run 命令增加 -e 参数

  • 2)cmd 中指定 Env 参数
    在exec命令fork新进程后,在cmd加入原有的pid的环境变量:
    cmd.Env = append(os.Environ(), env...)

    path := fmt.Sprintf("/proc/%s/environ", pid)
    contentBytes, err := os.ReadFile(path)
    envs := strings.Split(string(contentBytes), "\u0000")
    

效果
设置环境变量后,后台运行:
在这里插入图片描述

exec命令进入容器后,环境变量依然生效:
在这里插入图片描述

相关推荐

  1. Docker容器配置

    2024-06-10 06:30:02       188 阅读
  2. 指针

    2024-06-10 06:30:02       47 阅读
  3. CSS

    2024-06-10 06:30:02       46 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-10 06:30:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-10 06:30:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-06-10 06:30:02       87 阅读
  4. Python语言-面向对象

    2024-06-10 06:30:02       96 阅读

热门阅读

  1. Android防抖

    2024-06-10 06:30:02       37 阅读
  2. 高通Android 12/13添加/移除不被清理后台应用

    2024-06-10 06:30:02       31 阅读
  3. Docker面试整理-Docker Swarm与Kubernetes有什么区别?

    2024-06-10 06:30:02       29 阅读
  4. EF Core Model-First

    2024-06-10 06:30:02       26 阅读
  5. SOA的设计模式_1.服务注册表模式

    2024-06-10 06:30:02       31 阅读
  6. 209. 长度最小的子数组

    2024-06-10 06:30:02       35 阅读
  7. 主从式光伏并网发电系统体系结构

    2024-06-10 06:30:02       25 阅读
  8. ICESat-2 ATL08 数据批量读取

    2024-06-10 06:30:02       45 阅读