在 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