设为首页 收藏本站
查看: 779|回复: 0

[经验分享] docker 源码分析daemon2

[复制链接]

尚未签到

发表于 2017-12-6 14:34:06 | 显示全部楼层 |阅读模式
  run函数流程很简单
  func runDaemon(opts daemonOptions) error {
    if opts.version {   // 如果是查询版本,直接显示版本信息
        showVersion()
        return nil
    }
    daemonCli := NewDaemonCli()  //  daemon.go  新建一个daemoncli
    .... // windows 的特殊处理
    err = daemonCli.start(opts)   // daemon.go  关键语句,开始运行daemon
    notifyShutdown(err)  // 进程退出前的处理,只是windows系统在使用
    return err
}
  看下start的处理明显复杂很多
  func (cli *DaemonCli) start(opts daemonOptions) (err error) {
    stopc := make(chan bool)  // 创建一个通道,看上去退出时候阻塞用的
    defer close(stopc)  // 函数结束时候关闭通道

    // warn from uuid package when running the daemon
    uuid.Loggerf = logrus.Warnf

    opts.common.SetDefaultOptions(opts.flags)  // 同client,设置默认参数

    if cli.Config, err = loadDaemonCliConfig(opts); err != nil {  // 从opt里面将参数导入到config
        return err
    }
    cli.configFile = &opts.configFile  //  "/etc/docker/daemon.json"
    cli.flags = opts.flags
    ....  //config 的一些处理
    // Create the daemon root before we create ANY other files (PID, or migrate keys)
    // to ensure the appropriate ACL is set (particularly relevant on Windows)
    if err := daemon.CreateDaemonRoot(cli.Config); err != nil {   //  daemon/daemon.go  先创建daemon 的root路径,linux 为 /var/lib/docker
        return err
    }

    if cli.Pidfile != "" {    //  "/var/run/docker.pid "  非空则创建一个pidfile
        pf, err := pidfile.New(cli.Pidfile)
        if err != nil {
            return fmt.Errorf("Error starting daemon: %v", err)
        }
        defer func() {  //start函数结束的时候清除文件
            if err := pf.Remove(); err != nil {
                logrus.Error(err)
            }
        }()
    }

    serverConfig := &apiserver.Config{    ///  server 的config文件创建以及一些赋值
        Logging:     true,
        SocketGroup: cli.Config.SocketGroup,
        Version:     dockerversion.Version,
        EnableCors:  cli.Config.EnableCors,
        CorsHeaders: cli.Config.CorsHeaders,
    }
    .....

    api := apiserver.New(serverConfig)    // api/server/server.go 新建一个server的实例
    cli.api = api
  if len(cli.Config.Hosts) == 0 {
        cli.Config.Hosts = make([]string, 1)
    }
  for i := 0; i < len(cli.Config.Hosts); i++ {  // 循环根据配置文件里面所有host增加server的监听
        .......
        api.Accept(addr, ls...)
    }

    if err := migrateKey(cli.Config); err != nil {   // 把 key.json 移动到 /etc/docker 路径
        return err
    }
......

    registryService := registry.NewService(cli.Config.ServiceOptions)   // registry/service.go 新建一个default的registryserver
    containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...)   // libcontainerd/remote_unix.go
  //  /var/run/docker路径 ,创建 containerd Remote,container相关处理启动grpc的client api,事件监控等
  ....
    signal.Trap(func() {   // start时收到异常信息量的处理,关闭cli,其他地方处理结束才会给通道一个消息结束
        cli.stop()
        <-stopc // wait for daemonCli.start() to return
    })

    // Notify that the API is active, but before daemon is set up.
    preNotifySystem()   // 只是window系统有用

    d, err := daemon.NewDaemon(cli.Config, registryService, containerdRemote)   // daemon/daemon.go  新建daemon的所有东西,比较复杂,待后续分析
  .....

    if cli.Config.MetricsAddress != "" {  //  metrics 地址存在的话,起一个metrics server 监听
        if !d.HasExperimental() {
            return fmt.Errorf("metrics-addr is only supported when experimental is enabled")
        }
        if err := startMetricsServer(cli.Config.MetricsAddress); err != nil {
            return err
        }
    }

    name, _ := os.Hostname()

    c, err := cluster.New(cluster.Config{    // daemon/cluster/cluster.go  新建一个cluster 实例
        Root:                   cli.Config.Root,
        Name:                   name,
        Backend:                d,
        NetworkSubnetsProvider: d,
        DefaultAdvertiseAddr:   cli.Config.SwarmDefaultAdvertiseAddr,
        RuntimeRoot:            cli.getSwarmRunRoot(),
    })
......

    // Restart all autostart containers which has a swarm endpoint
    // and is not yet running now that we have successfully
    // initialized the cluster.
    d.RestartSwarmContainers()   // daemon/daemon.go   重启 container ,条件见函数内
......
    cli.d = d

    // initMiddlewares needs cli.d to be populated. Dont change this init order.
    if err := cli.initMiddlewares(api, serverConfig); err != nil {   //  给apiserver初始化中间件,要求cli.d必须被赋值
        logrus.Fatalf("Error creating middlewares: %v", err)
    }
    d.SetCluster(c)   //   d.cluster = c
    initRouter(api, d, c)   // 注册api消息处理函数,daemon命令的处理可以在这里面查

    cli.setupConfigReloadTrap()    //  设置一个系统调用重新加载配置

    // The serve API routine never exits unless an error occurs
    // We need to start it as a goroutine and wait on it so
    // daemon doesn't exit
    serveAPIWait := make(chan error)  //  等待错误的通道
    go api.Wait(serveAPIWait)  //  起server的协程,出现错误向serveAPIWait通道写入信息

    // after the daemon is done setting up we can notify systemd api
    notifySystem()    // 通知系统daemon 已经起来

    // Daemon is fully initialized and handling API traffic
    // Wait for serve API to complete
    errAPI := <-serveAPIWait  // 利用通道阻塞等待 server退出
    c.Cleanup()   // 关闭cluster
    shutdownDaemon(d)   // 关闭daemon
    containerdRemote.Cleanup()  // 关闭 container
......

    return nil
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-421349-1-1.html 上篇帖子: DOCKER 从入门到放弃(一) 下篇帖子: 自建docker swarm体验简单之美
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表