首页 > 代码库 > docker 源码分析client2

docker 源码分析client2

前面分析了使用cobra创建client,下面选取一条命令分析下client端如何执行

命令的处理都在cli目录之下,以 image 的 pull 为例

/cli/command/commands/commands.go  AddCommands函数增加命令注册

pull命令在 image.NewImageCommand(dockerCli) 里面

/cli/command/image/cmd.go 里定义了增加 pull命令 NewPullCommand(dockerCli),

/cli/command/image/pull.go 定义了pull命令

unc NewPullCommand(dockerCli *command.DockerCli) *cobra.Command {
    var opts pullOptions

    cmd := &cobra.Command{
        Use:   "pull [OPTIONS] NAME[:TAG|@DIGEST]",
        Short: "Pull an image or a repository from a registry",
        Args:  cli.ExactArgs(1),
        RunE: func(cmd *cobra.Command, args []string) error {
            opts.remote = args[0]
            return runPull(dockerCli, opts)  //pull命令的执行
        },
    }

    flags := cmd.Flags()

    flags.BoolVarP(&opts.all, "all-tags", "a", false, "Download all tagged images in the repository")
    command.AddTrustVerificationFlags(flags)

    return cmd
}

pull命令的运行也在改文件内,省略一些异常处理之后

func runPull(dockerCli *command.DockerCli, opts pullOptions) error {
    distributionRef, err := reference.ParseNormalizedNamed(opts.remote)  // 根据命令字符串获取domain的一些信息

    // Resolve the Repository name from fqn to RepositoryInfo
    repoInfo, err := registry.ParseRepositoryInfo(distributionRef)  //registry/config.go  调用newRepositoryInfo创建repsitory仓库的一些信息

    ctx := context.Background()   //上下文

    authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) // registry.go  创建鉴权的数据
    requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "pull") // registry.go  鉴权的函数

    // Check if reference has a digest
    _, isCanonical := distributionRef.(reference.Canonical)
    if command.IsTrusted() && !isCanonical {
        err = trustedPull(ctx, dockerCli, repoInfo, distributionRef, authConfig, requestPrivilege)  // trust.go  先获取Repository信息,在Repository获取所有Target信息,遍历target最终还是调用imagePullPrivileged
    } else {
        err = imagePullPrivileged(ctx, dockerCli, authConfig, reference.FamiliarString(distributionRef), requestPrivilege, opts.all)  //trust.go  该函数pull image 并且将结果回显
    }
}

创建repoinfo

//config := newServiceConfig(ServiceOptions{})

func newRepositoryInfo(config *serviceConfig, name reference.Named) (*RepositoryInfo, error) {
    index, err := newIndexInfo(config, reference.Domain(name))
    if err != nil {
        return nil, err
    }
    official := !strings.ContainsRune(reference.FamiliarName(name), ‘/‘)

    return &RepositoryInfo{
        Name:     reference.TrimNamed(name),
        Index:    index,
        Official: official,
    }, nil
}

// imagePullPrivileged pulls the image and displays it to the output

func imagePullPrivileged(ctx context.Context, cli *command.DockerCli, authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc, all bool) error {

    encodedAuth, err := command.EncodeAuthToBase64(authConfig)
    options := types.ImagePullOptions{
        RegistryAuth:  encodedAuth,
        PrivilegeFunc: requestPrivilege,
        All:           all,
    }

    responseBody, err := cli.Client().ImagePull(ctx, ref, options)  // client/image_pull.go  关键一句 cli.tryImageCreate(ctx, query, options.RegistryAuth)
    defer responseBody.Close()   // 执行完之后关闭

    return jsonmessage.DisplayJSONMessagesToStream(responseBody, cli.Out(), nil) //  显示json信息
}

 

func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
    headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
    return cli.post(ctx, "/images/create", query, nil, headers)
}

 

docker 源码分析client2