首页 > 编程语言 >浅入浅出docker run命令源码2-containerd篇

浅入浅出docker run命令源码2-containerd篇

时间:2024-12-14 13:31:00浏览次数:11  
标签:run 启动 浅入 containerd 代码 源码 dockerd go

1、前情回顾

在这里插入图片描述

上次《浅入浅出docker run命令源码》代码看到调用了grpc去让containerd启动容器就没有继续看了.

连一刻都没有为dockerd的无疾而终而哀悼,立刻来到战场的是containerd

在这里插入图片描述

这次,我们先解决下面的问题
1、dockerd是怎么启动的containerd
2、怎么调试containerd的源码
3、containerd架构
4、containerd接口对应的源码在哪里

2. dockerd 是怎么启动 containerd的?

dockerd 作为 Docker 服务的核心程序,在启动时会依赖列表和配置进行流程初始化,其中就包括 containerd 的启动。代码的位置很明显,一进来就可以看到
在这里插入图片描述

在这里插入图片描述

dockerd会先去看containerd是否已经启动,判断逻辑就是看/run/containerd/containerd.sock是否存在。如果不存在,继续往里面走,就会看到下面的代码
在这里插入图片描述

这里通过goroutine去启动containerd,然后创建一个定时器, 如果在15秒内没有启动成功就会会停止掉dockerd进程。这里会导致你debug不了后续的启动代码,这里需要修改以下这个超时时间,方便我们慢慢看参数。
在这里插入图片描述

修改为15分钟,重新编译dockerd代码, 如何编译请看我另一篇文章《docker源码阅读环境搭建》。继续debug, 可见调用了$PATH环境变量中的containerd…, 这是我以前安装docker时候docker安装的。
在这里插入图片描述

看到启动的命令了,接下来就是该怎么debug源码了。

3. 怎样调试 containerd 源码?

前面看到,如果containerd进程存在了,则不会再启动,而是直接使用已经启动的containerd进程,那么我们只需要编译源码后,用debug模式启动,等待dockerd进程访问即可。

因此我们得自己编译源代码,替换掉dockerd默认启动的二进制文件。
containerd的源码在另一个项目,所以得把源码拉下来先 , 拉取源码前需要 先看containerd的版本号,这个要看moby项目的vendor.mod文件,这里我的版本是

在这里插入图片描述

所以我们得clone对应的版本,在远程服务器上以及本地上都clone

   git clone --branch v1.7.24 --single-branch   https://github.com/containerd/containerd.git

官方的安装教程
https://github.com/containerd/containerd/blob/main/BUILDING.md

从安装文档得知,理论上我们还得编译containerd默认依赖的runc,但是由于我们之前通过apt已经安装过docker,所以这次先搞定containerd,等研究到runc再去折腾.

执行构建命令前需要先启动docker的守护进程, 我启动的是我编译好的

./bundles/binary-daemon/dockerd

安装文档里面写了可以用docker镜像来编译containerd
开始编译,我本地go的版本是1.23.3,找了个相近的版本,在containerd源码目录下

docker run -it \
    -v ${PWD}:/src/containerd \
    -w /src/containerd golang:1.23.4

然后在容器内输入命令

GODEBUG=1 make

等待编译完成即可。感觉这容器只是提供了go环境,并没有什么多大卵用,理论上直接在本地执行

GODEBUG=1 make

也是可以的。编译好后,二进制文件在 {源码目录}/bin 目录下。GoLand测试一下是否能debug

在这里插入图片描述

在远程服务器的源码根目录下执行下面的命令,需要加上前面从dockerd得到的参数
但是又不能直接用原来的配置文件,需要将配置文件复制到containerd源码根目目录下后,修改配置文件中xx.socket文件的路径如下
在这里插入图片描述

debug命令

dlv --listen=:8006 --headless=true --api-version=2 --accept-multiclient exec ./bin/containerd -- --config containerd.toml

containerd 源码的主函数位于 cmd/containerd/main.go,
GoLand打上断点运行,可以看到进来了
在这里插入图片描述

注意,需要containerd启动完成后,再启动dockerd

4. containerd 架构是怎样的

这是containerd官方的图,看起来应该就是它的架构图了
在这里插入图片描述

没怎么研究过,先简单看看就行,流程先走通,等需要再去研究。

5. containerd 接口代码在哪里?

containerd 源码的主函数位于 cmd/containerd/main.go

func main() {  
    app := command.App()  
    if err := app.Run(os.Args); err != nil {  
       fmt.Fprintf(os.Stderr, "containerd: %s\n", err)  
       os.Exit(1)  
    }  
}

跟踪进入 app.Run,发现最终调用了app.Action 函数。app.Action是在command.App()里面赋值的,继续看Action的逻辑
在这里插入图片描述

会看到调用了server方法去创建一个goroutine去启动监听服务。这个server就是我们要盯防的gRPC server。

众所周知,gprc需要使用 Protobuf 定义服务和消息格式,然后在用 protoc 编译器生成客户端和服务器的代码,最后在服务器端实现接口中定义的方法。启动流程代码如下:

server := grpc.NewServer()
service.Register(server)
server.Serve(listener)

那么接下来就是要找.proto文件以及service注册的逻辑在哪里了。

.proto文件
easy job,暴力ctrl + shift + f全局搜索后缀,发现在api包里面
在这里插入图片描述

service注册逻辑

在项目启动的时候,go的运行时会自动执行每个脚本的init()函数加载插件,如下图,
在这里插入图片描述

然后在创建 grpc server的时候进行初始化, 逻辑在创建server的函数里,会先把所有注册了的插件形成一个有序的集合,然后for循环处理,

plugins, err := LoadPlugins(ctx, config)
for _, p := range plugins {
	... 注册service
}

注册代码截图如下
在这里插入图片描述

这里的p就是在项目启动时由go运行时执行init函数注册的插件对象,p.Init就是调用对应其结构体中的函数变量InitFn,用来初始化插件的,service.Register里面就是要找的api.RegisterXXXXXServer(server, s)注册代码

最后值得一提的是,在 containerd 的代码结构中,gRPC 的实现通常被分为多个文件,比如 local.goservice.go。据说这种分工是为了将代码逻辑模块化,更清晰地划分功能和职责。具体如何还得看看代码才知道,简而言之就是
local.go 通常用于处理服务的本地实现逻辑,直接与底层模块交互。
service.go 用于定义 gRPC 服务的接口,实现与客户端的通信。

请求过来的时候,执行service.go中方法,其中会调用local.go中的方法来执行相应的处理逻辑。

他喵的,所以我要看的代码在哪里?
假设你再moby项目中,得到了请求路径如下:

/containerd.services.containers.v1.Containers/Create

1、直接搜/containerd.services.containers.v1.Containers/Create就能找到生成的xx_grpc.pb.go.proto文件就放在一起的。

2、接着在.proto文件中获取包名,
在这里插入图片描述

以截图例子,
package是消息的命名空间,是protobuf用来防止命名冲突的冲突的,如果没有go_package,也是生成代码的包路径,但如果有go_package,则以go_package为准, 包路径为在这里插入图片描述
github.com/containerd/containerd/api/services/containers/v1
,全局搜索包路径,看到有这两个组合的,一般处理逻辑代码就在这了

结论

啥都还没开始看呢。。。

标签:run,启动,浅入,containerd,代码,源码,dockerd,go
From: https://blog.csdn.net/wy53111/article/details/144469658

相关文章

  • springboot二手动漫周边交易网站-毕业设计源码16260
    目 录摘要1绪论1.1选题背景1.2研究意义1.3论文结构与章节安排2 二手动漫周边交易网站系统分析2.1可行性分析2.2系统流程分析2.2.1数据流程3.3.2业务流程2.3系统功能分析2.3.1功能性分析2.3.2非功能性分析2.4系统用例分析2.5本章小......
  • django停车场管理系统-毕业设计源码16856
    目 录1绪论1.1研究背景和意义1.2国内外研究现状1.3论文结构与章节安排2 系统分析2.1可行性分析2.1.1技术可行性分析2.1.2 经济可行性分析2.1.3操作可行性分析2.2系统功能分析2.2.1功能性分析2.2.2非功能性分析2.3 系统用例分析2.4系......
  • 免费送源码:Java+ssm+MySQL SSM智慧旅游系统 计算机毕业设计原创定制
     摘要随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。智慧旅游系统设计,主要的模块包括查看首页、站点内容(轮播图、公告栏)系统用户(管理员、注册用户、导游)公共内容(旅游资讯、资讯分类)模块管理(地区管理、景点信息......
  • 免费送源码:Java+B/S+MySQL 多元化智能选课系统的设计与实现 计算机毕业设计原创定制
    摘 要多元化智能选课系统使用Java语言的Springboot框架,采用MVVM模式进行开发,数据方面主要采用的是微软的Mysql关系型数据库来作为数据存储媒介,配合前台技术完成系统的开发。论文主要论述了如何使用JAVA语言开发一个多元化智能选课系统,本系统将严格按照软件开发流程进行各个......
  • 怎么才能修改网站源码,如何修改网站的源代码
    修改网站源码是网站维护和开发中的重要任务。以下是具体步骤:备份网站数据:在进行任何修改之前,务必先备份网站的数据和文件,以防出现问题。获取源码:如果你有网站的源码文件,可以直接下载到本地进行修改。如果没有源码文件,可以通过FTP客户端(如FileZilla)从服务器下载。......
  • 网站源码版权修改,如何修改网站源码中的版权信息
    修改网站源码中的版权信息是维护网站合法性和品牌一致性的重要步骤。以下是详细的步骤和技巧:备份数据:在进行任何修改前,备份网站的数据和代码,防止意外丢失。使用FTP客户端下载网站的全部文件,并导出数据库。定位版权信息:打开网站的HTML文件,通常是footer.html或index.htm......
  • 财务程序 SAAS版 财务系统 财务软件源码 云记账源码
    云记账源码是一款方便、易用的财务管理软件,适用于个人和小企业。它提供了简单的记账、财务分析、报表生成等功能,让您能够轻松管理您的财务。无论您是个人还是小企业,财务管理都是非常重要的。云记账源码通过数字化的方式,让您的财务管理更加简单、高效。您只需输入收入和支出,系......
  • 一对一视频源码,如何实现并发可重试的线程池?
    一对一视频源码,优雅的实现循环重试在一对一视频源码开发工作中,重处理是一个非常常见的场景,比如:发送消息失败。调用远程服务失败。争抢锁失败。这些错误可能是因为网络波动造成的,等待过后重处理就能成功。通常来说,会用try/catch,while循环之类的语法来进行重处理,但是这样的做法缺......
  • 基于Java中的SSM框架实现购物商城系统项目【项目源码+论文说明】计算机毕业设计
    摘要网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。因此商城购物信息的管理计算机化,系统化是必要的。设计开发购物商城系统......
  • 基于Java中的SSM框架实现个性化商铺系统项目【项目源码+论文说明】
    摘要随着信息化时代的到来,管理系统都趋向于智能化、系统化,个性化商铺系统也不例外,但目前国内的市场仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大,人工管理显然已无法应对时代的变化,而个性化商铺系统能很好地解决这一问题,轻松应对个性化商铺系统平时的工作,既能提高......