docker命令解析
来源:互联网 发布:ubuntu下安装windows 编辑:程序博客网 时间:2024/05/16 10:59
以前docker启动客户端和服务端使用的都是同一个命令(二进制可执行文件),现在docker将客户端程序和服务端程序分开了分别为docker和dockerd。而且docker的命令解析使用了一个第三方的库,名字叫cobra,github地址在:https://github.com/getting-started。客户端和服务端使用的是一样的命令解析方式,所以我们选取客户端分析docker的命令解析过程。
首先我们介绍下cobra这个库的简单用法,从cobra的github页面的例子中删减了下:
package mainimport ( "fmt" "github.com/spf13/cobra")func main() { //1.定义主命令 var Version bool var rootCmd = &cobra.Command{ Use: "root [sub]", Short: "My root command", //命令执行的函数 Run: func(cmd *cobra.Command, args []string) { fmt.Printf("Inside rootCmd Run with args: %v\n", args) if Version { fmt.Printf("Version:1.0\n") } }, } //2.定义子命令 var subCmd = &cobra.Command{ Use: "sub [no options!]", Short: "My subcommand", //命令执行的函数 Run: func(cmd *cobra.Command, args []string) { fmt.Printf("Inside subCmd Run with args: %v\n", args) }, } //添加子命令 rootCmd.AddCommand(subCmd) //3.为命令添加选项 flags := rootCmd.Flags() flags.BoolVarP(&Version, "version", "v", false, "Print version information and quit") //执行命令 _ = rootCmd.Execute()}
基本用法大概就是四步:
1.定义一个主命令(包含命令执行函数等)
2.定义若干子命令(包含命令执行函数等,根据需要可以为子命令定义子命令),并添加到主命令
3.为命令添加选项
4.执行命令
好了,了解了cobra的大概用法,我们从docker(客户端)的main函数开始分析
贴一下main函数:
func main() { // Set terminal emulation based on platform as required. stdin, stdout, stderr := term.StdStreams() logrus.SetOutput(stderr) dockerCli := command.NewDockerCli(stdin, stdout, stderr) //定义主命令 cmd := newDockerCommand(dockerCli) //执行命令 if err := cmd.Execute(); err != nil { if sterr, ok := err.(cli.StatusError); ok { if sterr.Status != "" { fmt.Fprintln(stderr, 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(stderr, err) os.Exit(1) }}
main函数中并没有我们前面提到的完整四步,而是使用了一个函数newDockerCommand来做了其他工作。我们接着分析该函数,代码不多,我们还是贴一下该函数代码:
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 { if opts.Version { showVersion() return nil } fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString()) return nil }, 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) return dockerCli.Initialize(opts) }, } //设置默认的处理方式 cli.SetupRootCommand(cmd) //为主命令添加选项 flags = cmd.Flags() flags.BoolVarP(&opts.Version, "version", "v", false, "Print version information and quit") flags.StringVar(&opts.ConfigDir, "config", cliconfig.ConfigDir(), "Location of client config files") //为主命令添加公共选项 opts.Common.InstallFlags(flags) //设置命令的输入 cmd.SetOutput(dockerCli.Out()) //添加daemon选项,其实已经作废了,应为新代码已经将客户端和服务端守护进程命令分开了,不需要这个选项区分启动客户端还是服务端 cmd.AddCommand(newDaemonCommand()) // AddCommands adds all the commands from cli/command to the root command //添加子命令及子命令的选项 commands.AddCommands(cmd, dockerCli) return cmd}
可以看到,表面上在该函数里面也只是定义了主命令,并为主命令添加了选项。那子命令呢?看到
//添加子命令及子命令的选项commands.AddCommands(cmd, dockerCli)
其实该函数的工作就是添加子命令,子命令的子命令,以及命令的选项。
// AddCommands adds all the commands from cli/command to the root commandfunc AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) { cmd.AddCommand( node.NewNodeCommand(dockerCli), service.NewServiceCommand(dockerCli), stack.NewStackCommand(dockerCli), stack.NewTopLevelDeployCommand(dockerCli), swarm.NewSwarmCommand(dockerCli), container.NewContainerCommand(dockerCli), image.NewImageCommand(dockerCli), system.NewSystemCommand(dockerCli), container.NewRunCommand(dockerCli), image.NewBuildCommand(dockerCli), network.NewNetworkCommand(dockerCli), hide(system.NewEventsCommand(dockerCli)), registry.NewLoginCommand(dockerCli), registry.NewLogoutCommand(dockerCli), registry.NewSearchCommand(dockerCli), system.NewVersionCommand(dockerCli), volume.NewVolumeCommand(dockerCli), hide(system.NewInfoCommand(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)), hide(system.NewInspectCommand(dockerCli)), checkpoint.NewCheckpointCommand(dockerCli), plugin.NewPluginCommand(dockerCli), )}
可以看到添加了很多子命令,这里面的都是一级子命令,也就是“docker xxx xxx xxx”中跟着docker的命令.注意到有些是被hide函数包裹的,有些则不是,我们在这里先不关心这个。我们选取一个命令docker images来分析
hide(image.NewImagesCommand(dockerCli)),
进入该函数:
// NewImagesCommand creates a new `docker images` commandfunc NewImagesCommand(dockerCli *command.DockerCli) *cobra.Command { opts := imagesOptions{filter: opts.NewFilterOpt()} cmd := &cobra.Command{ Use: "images [OPTIONS] [REPOSITORY[:TAG]]", Short: "List images", Args: cli.RequiresMaxArgs(1), //命令执行函数,有一个错误类型的变量作为返回值 RunE: func(cmd *cobra.Command, args []string) error { if len(args) > 0 { opts.matchName = args[0] } return runImages(dockerCli, opts) }, } //为命令添加选项 flags := cmd.Flags() flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only show numeric IDs") flags.BoolVarP(&opts.all, "all", "a", false, "Show all images (default hides intermediate images)") flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output") flags.BoolVar(&opts.showDigests, "digests", false, "Show digests") flags.StringVar(&opts.format, "format", "", "Pretty-print images using a Go template") flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided") return cmd}
当我们执行docker images时,就会执行命令中定义的函数,进而执行runImages(),改函数根据选项执行不同的操作。
- docker命令解析
- Docker命令全解析
- <Docker>01 命令参数解析
- [docker]docker命令 docker inspect
- docker 命令
- Docker 命令
- docker命令
- Docker命令
- docker命令
- Docker命令
- docker 命令
- Docker命令
- docker命令
- docker命令
- docker命令
- Docker 命令
- docker命令
- Docker 命令
- 天气类APP产品微体验(墨迹天气、中央天气预报、雅虎天气、2345天气王)
- 坑爹之Calendar.getInstance().get(Calendar.MONTH);
- Intent及intent-filter总结与使用
- VS2010调用OpenCV的相关配置问题
- Struts2的登录和权限控制用到的是拦截器
- docker命令解析
- 多层循环的意义
- 学习笔记:弱引用的使用
- [四格漫画] 第504话 网络相机
- selenium + python自动化测试环境搭建
- HDU - 1042 N!
- Linux GCC常用命令
- 华华对外心的探索
- codeforces100078H——History of Football