docker 源碼分析daemon 消息處理1

在 cmd/dockerd/daemon.go 文件 initRouter 函數中 初始化 routerdocker

    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 包json

image.go 新建路由 NewRouter 函數建立 imageRouter 實例並初始化路由api

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.gorestful

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  函數post

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 函數ui

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 函數,先分析到這裏spa

相關文章
相關標籤/搜索