• docker 源码分析daemon 消息处理1


    在 cmd/dockerd/daemon.go 文件 initRouter 函数中 初始化 router

        routers := []router.Router{
            checkpointrouter.NewRouter(d, decoder),
            container.NewRouter(d, decoder),
            image.NewRouter(d, decoder),
            systemrouter.NewRouter(d, c),
            volume.NewRouter(d),
            build.NewRouter(dockerfile.NewBuildManager(d)),
            swarmrouter.NewRouter(c),
            pluginrouter.NewRouter(d.PluginManager()),
        }

    以pull命令为例, image的处理函数在 api/server/router/image 的image 包

    image.go 新建路由 NewRouter 函数创建 imageRouter 实例并初始化路由

    func (r *imageRouter) initRoutes() {
        r.routes = []router.Route{
            // GET
            router.NewGetRoute("/images/json", r.getImagesJSON),
            router.NewGetRoute("/images/search", r.getImagesSearch),
            router.NewGetRoute("/images/get", r.getImagesGet),
            router.NewGetRoute("/images/{name:.*}/get", r.getImagesGet),
            router.NewGetRoute("/images/{name:.*}/history", r.getImagesHistory),
            router.NewGetRoute("/images/{name:.*}/json", r.getImagesByName),
            // POST
            router.NewPostRoute("/commit", r.postCommit),
            router.NewPostRoute("/images/load", r.postImagesLoad),
            router.Cancellable(router.NewPostRoute("/images/create", r.postImagesCreate)),
            router.Cancellable(router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush)),
            router.NewPostRoute("/images/{name:.*}/tag", r.postImagesTag),
            router.NewPostRoute("/images/prune", r.postImagesPrune),
            // DELETE
            router.NewDeleteRoute("/images/{name:.*}", r.deleteImages),
        }
    }

    pull命令对应的restful api是"/images/create", 会调用 imageRouter 的postImagesCreate 函数,函数位于image包的image_routes.go

    func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    ...
        if image != "" { //pull
    ....
            err = s.backend.PullImage(ctx, image, tag, metaHeaders, authConfig, output)
        } else { //import
    ...
            err = s.backend.ImportImage(src, repo, tag, message, r.Body, output, r.Form["changes"])
        }
    ...
    }

    函数解码之后对于pull命令调用imageRouter 的 backend.PullImage

    image包中backend.go是一些接口,真正的backend是初始化时传入的daemon,因此调用的是 daemon/image_pull.go的 PullImage  函数

    func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
        ...
        return daemon.pullImageWithReference(ctx, ref, metaHeaders, authConfig, outStream)
    }

    如果传入tag,则需要处理tag,然后调用pullImageWithReference 函数

    func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
        progressChan := make(chan progress.Progress, 100)
    
        writesDone := make(chan struct{})
    
        ctx, cancelFunc := context.WithCancel(ctx)
    
        go func() {
            progressutils.WriteDistributionProgress(cancelFunc, outStream, progressChan)
            close(writesDone)
        }()
    
        imagePullConfig := &distribution.ImagePullConfig{
    ....
        }
    
        err := distribution.Pull(ctx, ref, imagePullConfig)
        close(progressChan)
        <-writesDone
        return err
    }
    progressChan 通道是用来显示pull操作的状态, writesDone 用来等待协程处理结束,创建config实例,调用 distribution/pull.go 内的Pull 函数
    func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullConfig) error {
        repoInfo, err := imagePullConfig.RegistryService.ResolveRepository(ref)
        ...
    
        endpoints, err := imagePullConfig.RegistryService.LookupPullEndpoints(reference.Domain(repoInfo.Name))
        .....
        for _, endpoint := range endpoints {
        ...
    
            puller, err := newPuller(endpoint, repoInfo, imagePullConfig)
    ...
            if err := puller.Pull(ctx, ref); err != nil {
        .....
            }
    ...
        }
    ....
    }

    获取仓库端信息,遍历端点,根据api版本创建V1或V2版本的puller的Pull 函数,先分析到这里

  • 相关阅读:
    js-事件总结
    iquery-个人总结
    CSS3-页面样式
    野生码农狂奔中的2014年度年终总结
    算不算被虚度的这几年
    在Ubuntu 12.4 下安装 nginx, MySQL, PHP
    使用WP8最新的AudioVideoCaptureDevice类制作录像应用
    WP8 MediaElement 实现循环播放
    WPF(WP7、WP8)多个Listbox嵌套时滚动问题的解决
    Weibo SDK WP版本回调参数没有uid的解决方法
  • 原文地址:https://www.cnblogs.com/arwen-spy/p/6629256.html
Copyright © 2020-2023  润新知