docker命令行解析以及如何向服务器端发送请求

最近在看doccker的源码,最新的master分支(估计是1.12.4,因为最新的release是1.12.3)命令行解析全部都使用了第3方的包https://github.com/spf13/cobra。然后看了一下别的分支的代码,感觉结构确实清晰了很多,可读性变高了不少。先看一下如何去使用。

客户端main()在docker/docker/cmd/docker下,可以直接使用go build编译(把vendor下的依赖包移出来就可以了)。

L20-58:

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())
	cmd.AddCommand(newDaemonCommand())
	commands.AddCommands(cmd, dockerCli)

	return cmd
}

这个方法会完成所有命令行规则的添加,和相应执行的方法。RunE: func(cmd *cobra.Command, args []string) error {}是命令执行的方法,flags是参数的解析。当我们输入docker -v,执行showversion()方法,*cobra.Command结构体是一个树的结构,docker下面有很多的子命令,比如docker image,然后image下面可以添加参数 -a等,最后只要在main()中执行cmd.Execute()就可以完成所有解析,这是也是第3方包的方法。

ctrl+鼠标右键点击进入commands.AddCommands(cmd, dockerCli)

func 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),
。。。)
}

封装了一下cmd.AddCommand()方法,然后node.service.stack.swarm.container这些包都写了个大写new方法来创建命令,继续进入container.NewContainerCommand(dockerCli),这是所有的方法都传入了dockerCli(单例模式直视感),

func NewContainerCommand(dockerCli *command.DockerCli) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "container",
		Short: "Manage containers",
		Args:  cli.NoArgs,
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
		},
	}
	cmd.AddCommand(
		NewAttachCommand(dockerCli),
		NewCommitCommand(dockerCli),
		NewCopyCommand(dockerCli),
		NewCreateCommand(dockerCli),
		NewDiffCommand(dockerCli),
		NewExecCommand(dockerCli),
		NewExportCommand(dockerCli),
		NewKillCommand(dockerCli),
		NewLogsCommand(dockerCli),
		NewPauseCommand(dockerCli),
		NewPortCommand(dockerCli),
		NewRenameCommand(dockerCli),
		NewRestartCommand(dockerCli),
		NewRmCommand(dockerCli),
		NewRunCommand(dockerCli),
		NewStartCommand(dockerCli),
		NewStatsCommand(dockerCli),
		NewStopCommand(dockerCli),
		NewTopCommand(dockerCli),
		NewUnpauseCommand(dockerCli),
		NewUpdateCommand(dockerCli),
		NewWaitCommand(dockerCli),
		newListCommand(dockerCli),
		newInspectCommand(dockerCli),
		NewPruneCommand(dockerCli),
	)
	return cmd
}

  docker contain下又添加了很多的命令,继续进入

func NewCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
	var opts createOptions
	var copts *runconfigopts.ContainerOptions

	cmd := &cobra.Command{
		Use:   "create [OPTIONS] IMAGE [COMMAND] [ARG...]",
		Short: "Create a new container",
		Args:  cli.RequiresMinArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			copts.Image = args[0]
			if len(args) > 1 {
				copts.Args = args[1:]
			}
			return runCreate(dockerCli, cmd.Flags(), &opts, copts)
		},
	}

	flags := cmd.Flags()
	flags.SetInterspersed(false)

	flags.StringVar(&opts.name, "name", "", "Assign a name to the container")

	// Add an explicit help that doesn‘t have a `-h` to prevent the conflict
	// with hostname
	flags.Bool("help", false, "Print usage")

	command.AddTrustedFlags(flags, true)
	copts = runconfigopts.AddFlags(flags)
	return cmd
}

  这里可以看到解析了name和help,docker run create命令就是这么来的,然后看一下RunE中是如何向服务器端发送请求的,继续进入最后可以得到一个这个方法,response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name)

func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error) {
	var response types.ContainerCreateResponse
	query := url.Values{}
	if containerName != "" {
		query.Set("name", containerName)
	}

	body := configWrapper{
		Config:           config,
		HostConfig:       hostConfig,
		NetworkingConfig: networkingConfig,
	}

	serverResp, err := cli.post(ctx, "/containers/create", query, body, nil)
	if err != nil {
		if serverResp != nil && serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
			return response, imageNotFoundError{config.Image}
		}
		return response, err
	}

	err = json.NewDecoder(serverResp.body).Decode(&response)
	ensureReaderClosed(serverResp)
	return response, err
}

发送post /containers/create请求,细节的地方需要继续去看,服务器端的命令解析也是一样的,目录在docker/docker/cmd/dockerd下,go编译的包是通过包名获取的,所以deamon的命令就是dockerd,有一个很好的方法是dockerd -D,可以看到调试的信息,service api的添加,网络的初始化等。。

https://github.com/zjj2wry/httptest,这是拿那个命令行解析写的一个post请求,可以携带参数,cookies等,然后生成接口文档,对我已经完全够了(目前业务百分之90都是post),主要写个接口得给前端一个文档,偷个懒。。

时间: 2024-10-30 17:08:00

docker命令行解析以及如何向服务器端发送请求的相关文章

python命令行解析工具argparse模块【1】

argpaser是python中很好用的一个命令行解析模块,使用它我们可以很方便的创建用户友好型命令行程序.而且argparse会自动生成帮助信息和错误信息. 一.示例 例如下面的例子,从命令行中获取几个整数,然后获取它们的和或者最大值. import argparse parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('integers', metavar='N'

cmdline —— 轻量级的C++命令行解析库

平时用C++写一些命令行工具,需要解析命令行的输入参数,这是一项繁琐并且容易出错的工作,我们不应该将主要精力放在这上面,可以考虑使用开源的库,下面的cmdline就是其中非常好用的一款. cmdline介绍 cmdline 是一个非常简单好用的C++命令行解析库,其基于模板,所以使用很简单,写出的代码也很优雅.由于其只包含一个头文件,所以很容易集成到自己的项目中. cmdline项目托管地址Github:https://github.com/tanakh/cmdline cmdline使用 下面

深入浅出Docker(二):Docker命令行探秘

1. Docker命令行 Docker官方为了让用户快速了解Docker,提供了一个交互式教程,旨在帮助用户掌握Docker命令行的使用方法.但是由于Docker技术的快速发展,此交互式教程已经无法满足Docker用户的实际使用需求,所以让我们一起开始一次真正的命令行学习之旅.首先,Docker的命令清单可以通过运行docker ,或者 docker help 命令得到: $ sudo docker 在Docker容器技术不断演化的过程中,Docker的子命令已经达到34个之多,其中核心子命令(

ZMAN的学习笔记之Python篇:命令行解析

ZMAN的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:ZMAN  (http://www.cnblogs.com/zmanone/) 在Python中,对命令行的解析方式不唯一,本文将介绍两种方法:一种是用sys.argv手动设置,另一种是用argparse模块. 一.sys.argv是什么 首先看一个例子: import sys print(len(sys.argv)) for arg in sys.argv: print(arg) 将

【C++】cmdline —— 轻量级的C++命令行解析库

平时用C++写一些命令行工具,须要解析命令行的输入參数,这是一项繁琐而且easy出错的工作,我们不应该将主要精力放在这上面.能够考虑使用开源的库.以下的cmdline就是当中很好用的一款. cmdline介绍 cmdline 是一个非常easy好用的C++命令行解析库,其基于模板.所以使用非常easy,写出的代码也非常优雅. 因为其仅仅包括一个头文件.所以非常easy集成到自己的项目中. cmdline项目托管地址Github:https://github.com/tanakh/cmdline

Docker命令行与守护进程如何交互?

译者按: Docker是典型的C/S架构,其守护进程(daemon)与命令行(CLI)是通过REST API进行交互的. 原文: Understanding how the Docker Daemon and Docker CLI Work Together 译者: Fundebug 为了保证可读性,本文采用意译而非直译.另外,本文版权归原作者所有,翻译仅用于学习. Docker并非单体应用,它由多个组件构成.这篇博客将介绍Docker守护进程(daemon)与Docker命令行(CLI).事实

python之命令行解析工具argparse

以前写python的时候都会自己在文件开头写一个usgae函数,用来加上各种注释,给用这个脚本的人提供帮助文档. 今天才知道原来python已经有一个自带的命令行解析工具argparse,用了一下,效果还不错. argparse的官方文档请看 https://docs.python.org/2/howto/argparse.html#id1 from argparse import ArgumentParser p = ArgumentParser(usage='it is usage tip'

转:python命令行解析工具Argparse

转自:http://www.cnblogs.com/jianboqi/archive/2013/01/10/2854726.html 最近在研究pathon的命令行解析工具,argparse,它是Python标准库中推荐使用的编写命令行程序的工具. 以前老是做UI程序,今天试了下命令行程序,感觉相当好,不用再花大把时间去研究界面问题,尤其是vc++中尤其繁琐. 现在用python来实现命令行,核心计算模块可以用c自己写扩展库,效果挺好. 学习了argparse,在官方文档中找到一篇toturia

使用命令行解析php文件

使用命令行解析php文件,这样可以调用Log4PHP库中的一些demo,因为默认的输出使用命令行作为输出. 建一个bat文件: echo 以下是使用命令行解析php文件 C:\xampp\php\php.exe C:\xampp\htdocs\JsonDemo.php pause 直接执行即可.