docker1.9源码分析(一):执行主函数以及命令行解析

主函数在docker/docker/docker.go中,首先是flag包处理参数,根据输入的参数执行相应的操作,之后

clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags)
根据输入的clientFlags参数新建docker client

c := cli.New(clientCli, daemonCli)
建立命令行接口,其中cli是要执行的命令,根据参数可以是client,server,daemon端任意的命令

if err := c.Run(flag.Args()...); err != nil {
   if sterr, ok := err.(cli.StatusError); ok {
      if sterr.Status != "" {
         fmt.Fprintln(os.Stderr, sterr.Status)
         os.Exit(1)
      }
      os.Exit(sterr.StatusCode)
   }
   fmt.Fprintln(os.Stderr, err)
   os.Exit(1)
}
其中Run()函数的实现在docker/cli/cli.go中,如下所示:

func (cli *Cli) Run(args ...string) error {
   if len(args) > 1 {
      command, err := cli.command(args[:2]...)
      switch err := err.(type) {
      case nil:
         return command(args[2:]...)
      case initErr:
         return err.error
      }
   }
   if len(args) > 0 {
      command, err := cli.command(args[0])
      switch err := err.(type) {
      case nil:
         return command(args[1:]...)
      case initErr:
         return err.error
      }
      cli.noSuchCommand(args[0])
   }
   return cli.CmdHelp()
}
其中command()函数解析出具体要执行的命令,所以该函数执行用户输入的命令,然后根据解析出的函数名进入相应的Cmd执行,比如用户输入的是docker pull命令,那么就会执行docker/api/client/pull.go中的client.CmdPull函数,如下所示:

func (cli *DockerCli) CmdPull(args ...string) error {
   cmd := Cli.Subcmd("pull", []string{"NAME[:TAG|@DIGEST]"}, Cli.DockerCommands["pull"].Description, true)
   allTags := cmd.Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository")
   addTrustedFlags(cmd, true)
   cmd.Require(flag.Exact, 1)

   cmd.ParseFlags(args, true)
   remote := cmd.Arg(0)

   taglessRemote, tag := parsers.ParseRepositoryTag(remote)
   if tag == "" && !*allTags {
      tag = tags.DefaultTag
      fmt.Fprintf(cli.out, "Using default tag: %s\n", tag)
   } else if tag != "" && *allTags {
      return fmt.Errorf("tag can't be used with --all-tags/-a")
   }

   ref := registry.ParseReference(tag)

   // Resolve the Repository name from fqn to RepositoryInfo
   repoInfo, err := registry.ParseRepositoryInfo(taglessRemote)
   if err != nil {
      return err
   }

   if isTrusted() && !ref.HasDigest() {
      // Check if tag is digest
      authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index)
      return cli.trustedPull(repoInfo, ref, authConfig)
   }

   v := url.Values{}
   v.Set("fromImage", ref.ImageName(taglessRemote))

   _, _, err = cli.clientRequestAttemptLogin("POST", "/images/create?"+v.Encode(), nil, cli.out, repoInfo.Index, "pull")
   return err
}
首先是建立命令参数,之后是命令的解析

remote:镜像仓库全地址

taglessRemote:不带tag的的仓库地址

tag:tag值

repoInfo, err := registry.ParseRepositoryInfo(taglessRemote)

这一行代码将taglessRemote解析成一个RepositoryInfo,其实是将remoteName换成一种docker源码可以执行的表现形式,该结构体如下:

// RepositoryInfo describes a repository
type RepositoryInfo struct {
   // Index points to registry information
   Index *IndexInfo
   // RemoteName is the remote name of the repository, such as
   // "library/ubuntu-12.04-base"
   RemoteName string
   // LocalName is the local name of the repository, such as
   // "ubuntu-12.04-base"
   LocalName string
   // CanonicalName is the canonical name of the repository, such as
   // "docker.io/library/ubuntu-12.04-base"
   CanonicalName string
   // Official indicates whether the repository is considered official.
   // If the registry is official, and the normalized name does not
   // contain a '/' (e.g. "foo"), then it is considered an official repo.
   Official bool
}
其中,IndexInfo是镜像仓库主机的信息,"Name"是主机名,当为docker hub时,Official的值为true,私有仓库时值为false;RemoteName是在仓库中存储的值,LocalName是在本地节点中存储的名,CanonicalName是全名。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值