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

来源:互联网 发布:windows createfile 编辑:程序博客网 时间:2024/06/14 05:20

主函数在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 repositorytype 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 0
原创粉丝点击