通过docker cli 源码跟踪docker镜像签名

Docker代码更新很快,Docker项目更名为moby,然后很多组件又从moby中拆分了出来。其中docker client的源码如下:
https://github.com/docker/cli 目前最新的版本是18.09,可直接下载或通过gitclone下载。将项目放在如下目录:cli-master

1、入口文件在cmd/docker/docker.go

func main() {	
     dockerCli, err := command.NewDockerCli()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	logrus.SetOutput(dockerCli.Err())
	if err := runDocker(dockerCli); err != nil {
		if sterr, ok := err.(cli.StatusError); ok {
			if sterr.Status != "" {	
			fmt.Fprintln(dockerCli.Err(), sterr.Status)
			}
			// StatusError should only be used for errors, and all errors should
			// have a non-zero exit status, so never exit with 0
			if sterr.StatusCode == 0 {
				os.Exit(1)
			}
			os.Exit(sterr.StatusCode)
		}
		fmt.Fprintln(dockerCli.Err(), err)
		os.Exit(1)
	}
}

2、跳到上面的runDocker(dockerCli)函数中:

func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command {
    opts := cliflags.NewClientOptions()
    var flags *pflag.FlagSet

    cmd := &cobra.Command{
        Use:              "docker [OPTIONS] COMMAND [ARG...]",
        Short:            "A self-sufficient runtime for containers",
        SilenceUsage:     true,
        SilenceErrors:    true,
        TraverseChildren: true,
        Args:             noArgs,
        RunE: func(cmd *cobra.Command, args []string) error {
            return command.ShowHelp(dockerCli.Err())(cmd, args)
        },
        PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
            // flags must be the top-level command flags, not cmd.Flags()
            opts.Common.SetDefaultOptions(flags)
            dockerPreRun(opts)
            if err := dockerCli.Initialize(opts); err != nil {
                return err
            }
            return isSupported(cmd, dockerCli)
        },
        Version:               fmt.Sprintf("%s, build %s", cli.Version, cli.GitCommit),
        DisableFlagsInUseLine: true,
    }
    //将cmd里的设置为root命令
    cli.SetupRootCommand(cmd)

    flags = cmd.Flags()
    flags.BoolP("version", "v", false, "Print version information and quit")
    flags.StringVar(&opts.ConfigDir, "config", cliconfig.Dir(), "Location of client config files")
    opts.Common.InstallFlags(flags)

    setFlagErrorFunc(dockerCli, cmd, flags, opts)

    setHelpFunc(dockerCli, cmd, flags, opts)

    cmd.SetOutput(dockerCli.Out())
    //添加子命令,cmd里是root命令
    commands.AddCommands(cmd, dockerCli)

    disableFlagsInUseLine(cmd)
    setValidateArgs(dockerCli, cmd, flags, opts)

    return cmd
}

3、commands.AddCommands(cmd, dockerCli)跳转到cli/command/commands/commands.go

func AddCommands(cmd *cobra.Command, dockerCli command.Cli) {
   cmd.AddCommand(
       // checkpoint
       checkpoint.NewCheckpointCommand(dockerCli),

       // config
       config.NewConfigCommand(dockerCli),

       // container
       container.NewContainerCommand(dockerCli),
       container.NewRunCommand(dockerCli),

       // image
       image.NewImageCommand(dockerCli),
       image.NewBuildCommand(dockerCli),

       // builder
       builder.NewBuilderCommand(dockerCli),

       // manifest
       manifest.NewManifestCommand(dockerCli),

       // network
       network.NewNetworkCommand(dockerCli),

       // node
       node.NewNodeCommand(dockerCli),

       // plugin
       plugin.NewPluginCommand(dockerCli),

       // registry
       registry.NewLoginCommand(dockerCli),
       registry.NewLogoutCommand(dockerCli),
       registry.NewSearchCommand(dockerCli),

       // secret
       secret.NewSecretCommand(dockerCli),

       // service
       service.NewServiceCommand(dockerCli),

       // system
       system.NewSystemCommand(dockerCli),
       system.NewVersionCommand(dockerCli),

       // stack
       stack.NewStackCommand(dockerCli),
       stack.NewTopLevelDeployCommand(dockerCli),

       // swarm
       swarm.NewSwarmCommand(dockerCli),

       // trust
       trust.NewTrustCommand(dockerCli),

       // volume
       volume.NewVolumeCommand(dockerCli),

       // legacy commands may be hidden
       hide(system.NewEventsCommand(dockerCli)),
       hide(system.NewInfoCommand(dockerCli)),
       hide(system.NewInspectCommand(dockerCli)),
       hide(container.NewAttachCommand(dockerCli)),
       hide(container.NewCommitCommand(dockerCli)),
       hide(container.NewCopyCommand(dockerCli)),
       hide(container.NewCreateCommand(dockerCli)),
       hide(container.NewDiffCommand(dockerCli)),
       hide(container.NewExecCommand(dockerCli)),
       hide(container.NewExportCommand(dockerCli)),
       hide(container.NewKillCommand(dockerCli)),
       hide(container.NewLogsCommand(dockerCli)),
       hide(container.NewPauseCommand(dockerCli)),
       hide(container.NewPortCommand(dockerCli)),
       hide(container.NewPsCommand(dockerCli)),
       hide(container.NewRenameCommand(dockerCli)),
       hide(container.NewRestartCommand(dockerCli)),
       hide(container.NewRmCommand(dockerCli)),
       hide(container.NewStartCommand(dockerCli)),
       hide(container.NewStatsCommand(dockerCli)),
       hide(container.NewStopCommand(dockerCli)),
       hide(container.NewTopCommand(dockerCli)),
       hide(container.NewUnpauseCommand(dockerCli)),
       hide(container.NewUpdateCommand(dockerCli)),
       hide(container.NewWaitCommand(dockerCli)),
       hide(image.NewHistoryCommand(dockerCli)),
       hide(image.NewImagesCommand(dockerCli)),
       hide(image.NewImportCommand(dockerCli)),
       hide(image.NewLoadCommand(dockerCli)),
       hide(image.NewPullCommand(dockerCli)),
       hide(image.NewPushCommand(dockerCli)),
       hide(image.NewRemoveCommand(dockerCli)),
       hide(image.NewSaveCommand(dockerCli)),
       hide(image.NewTagCommand(dockerCli)),
   )
   if runtime.GOOS == "linux" {
       // engine
       cmd.AddCommand(engine.NewEngineCommand(dockerCli))
   }
}
4、通过 image.NewImageCommand(dockerCli),跳转到cli/command/image/cmd.go

  func NewImageCommand(dockerCli command.Cli) *cobra.Command {
    cmd := &cobra.Command{
        Use:   "image",
        Short: "Manage images",
        Args:  cli.NoArgs,
        RunE:  command.ShowHelp(dockerCli.Err()),
    }
    cmd.AddCommand(
        NewBuildCommand(dockerCli),
        NewHistoryCommand(dockerCli),
        NewImportCommand(dockerCli),
        NewLoadCommand(dockerCli),
        NewPullCommand(dockerCli),
        NewPushCommand(dockerCli),
        NewSaveCommand(dockerCli),
        NewTagCommand(dockerCli),
        newListCommand(dockerCli),
        newRemoveCommand(dockerCli),
        newInspectCommand(dockerCli),
        NewPruneCommand(dockerCli),
    )
    return cmd
}    

5、通过    NewPushCommand(dockerCli)进行跳转cli/command/image/push.go

func NewPushCommand(dockerCli command.Cli) *cobra.Command 
	var opts pushOptions
	cmd := &cobra.Command{
		Use:   "push [OPTIONS] NAME[:TAG]",
		Short: "Push an image or a repository to a registry",
		Args:  cli.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			opts.remote = args[0]
			return RunPush(dockerCli, opts)
		},
	}
	flags := cmd.Flags()
	command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled())
	return cmd
}

func RunPush(dockerCli command.Cli, opts pushOptions) error {

ref, err := reference.ParseNormalizedNamed(opts.remote)

if err != nil {

return err

}

// Resolve the Repository name from fqn to RepositoryInfo

repoInfo, err := registry.ParseRepositoryInfo(ref)

if err != nil {

return err

}

ctx := context.Background()

// Resolve the Auth config relevant for this server

authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)

requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push")

//通过opts.untrusted判断是否对进行进行签名

if !opts.untrusted {

return TrustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege)

}

// TrustedPush handles content trust pushing of an image

通过TrustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege)跳转到cli/command/image/trust.go

func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
	responseBody, err := imagePushPrivileged(ctx, cli, authConfig, ref, requestPrivilege)	if err != nil {
		return err
}	
defer responseBody.Close()	
return PushTrustedReference(cli, repoInfo, ref, authConfig, responseBody)
}

通过PushTrustedReference完成与notary的通信,完成镜像的签名。

RunPush函数中还有另外一个方法:

responseBody, err := imagePushPrivileged(ctx, dockerCli, authConfig, ref, requestPrivilege)	
 
if err != nil {
		
    return err	
}

通过imagePushPrivileged方法将镜像推送到registry中

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值