• docker-server(moby)源码窥探


    docker 服务端的代码,已经被单独划分为一个仓库:moby。此文将分析dockerd在启动过程中的重要步骤。为了节省篇幅,突出显示重要部分,在源码的截图中将以…代替次要的逻辑,仅保留重要的信息。

    入口函数main()

    入口函数在/root/go/src/github.com/docker/docker/cmd/dockerd/docker.go中。

    在main() 函数中,除基本的设置外,包含两个重要的函数,分别为newDaemonCommand()和Execute()。newDaemonCommand()返回一个dockerd命令,Execute()则负责执行这个命令。

    在这里插入图片描述

    newDaemonCommand()

    newDaemonCommand() 与 docker-cli中设置命令的方法类似,其中最主要的还是runE字段的对应的函数,后面在执行的过程中,会调用该函数。

    除了runE字段外,还包括一些flag参数设置,这些都不涉及重要的流程。

    在这里插入图片描述

    Execute()

    Execute() 内部直接调用了ExecuteC()

    在这里插入图片描述

    ExecuteC()

    ExecuteC()中先通过Find() 获取解析出实际的命令,此处如果是没有子命令的场景,其实c 和 cmd变量是同样的内容。相当于没有变化。具体的Find()执行过程,与docker-cli项目中的Find()是一样的,详情可以移步至:https://zhh0427.blog.csdn.net/article/details/127796562

    获取到cmd之后,通过execute(), 执行该命令,

    在这里插入图片描述

    execute()

    execute()中主要的就是RunE()的调用,当然还包括一些其他的前置和后置处理,这里就不赘述了。

    在这里插入图片描述

    此处调用的RunE,即是在newDaemonCommand()中设置的RunE字段,可以发现RunE中的runDaemon()其实才是真正开始运行服务,之前的都是为dockerd这个命令做的配置,都是铺垫此处的。

    在这里插入图片描述

    runDaemon()

    runDaemon()的整体逻辑也比较简单,就是先实例化一个DaemonCli(), 接着开启该Cli。

    在这里插入图片描述

    start()

    start()包含对DaemonCli的配置、初始化、以及对操作系统的适配、基础环境的创建、swarm、集群模式的配置等等一系列的操作,这里很难一一讲清楚。不过,其中与日常单机使用最相关的,当属apiServer部分的逻辑。

    这部分逻辑中,主要分为三个步骤:1. 先创建apiServerConfig 配置 2. 根据配置初始化路由,即各个api对应函数 3.路由初始化完成后,通过开启协程开始监听客户端的发来的请求。其中配置部分的逻辑比较简单,更重要的是initRouter()和cli.api.Wait()。

    在这里插入图片描述

    initRouter()

    在initRouter()中,可以发现通过NewRouter()各个模块的实例化路由的动作,包括 容器相关、镜像相关、挂载卷相关的等等。

    在实例化完成后,最终调用InitRouter()对所有的路由作进一步处理。

    在这里插入图片描述

    NewRouter()

    这里仅对container.NewRouter()做分析,其他的模块都是相似的逻辑。NewRouter()中直接调用了initRoutes()。而initRoutes()中包含了大量的url注册,其中值得注意的是/containers/json, 不知道是否还记得,docker ps -a 最终发起的http请求的路径,没错就是该路由(如果不清楚,请移步至:https://zhh0427.blog.csdn.net/article/details/127796562)。

    由此可见,执行docker ps -a 获得的数据,其实是通过此处返回的,getContainersByName()具体的执行逻辑,这里就不赘述了,请自行查阅。
    在这里插入图片描述

    在这里插入图片描述

    InitRouter()

    在InitRouter()中,似乎是仅仅将各个路由赋值给了s.routers,其他啥也没干,其实不然,请记住这里的s.routers。

    在这里插入图片描述

    Wait()

    在Wait()中,通过serverAPI()开启对各个路由的监听。

    在这里插入图片描述

    serveAPI()

    在serverAPI()中,通过createMux() 初始化服务器使用的各个路由,然后通过Server开启监听。

    在这里插入图片描述

    createMux()

    在createMux()中,可以发现前面被赋值的s.routers 在这里发挥了作用。通过遍历每一个routers中的所有route,并为其注册路由。

    在这里插入图片描述

    Serve()

    最终在Server() 中,监听路由,等待客户端发来的请求,并分发到对应的处理器中。

    在这里插入图片描述

    至此,整个docker-server的启动主要过程就结束了。除了上述这些我认为重要的步骤,还有很多很多其他的步骤。很难在短时间内完全搞清楚,也很难一一讲清楚,具体的实现细节,还需要读者自行去查阅源代码。这里提供一个搭建docker源码阅读环境的教程:https://zhh0427.blog.csdn.net/article/details/127797712。

    如果上述有错误的地方,还请评论区指正,谢谢!

  • 相关阅读:
    wsl ubuntu18.04升级为cmake-3.15.3
    adele心理学
    4. client-go 编程式交互
    人工神经网络概念及组成,人工神经网络基本结构
    Android 12(S) 图像显示系统 - BufferQueue的工作流程(八)
    软件测试基本原则
    【机器学习】划分训练集和测试集的方法
    Python中TensorFlow的长短期记忆神经网络(LSTM)、指数移动平均法预测股票市场和可视化...
    如何应对客户讨价还价的套路?
    一步步来,如何提高语言表达能力,提高说服能力
  • 原文地址:https://blog.csdn.net/hg_zhh/article/details/127876098