Go语言实现通过Docker SDK获取docker ps 命令信息&SDK 中docker ps源码解析

在命令行中我们可以通过docker ps命令去获取当前正在执行的容器。那么怎么在程序中获取到这些信息呢?

这里使用的是Docker GO语言的SDK,官网参考链接为:SDK 除了GO语言外,还支持Python语言和HTTP获取。

一、首先需要获取到SDK的依赖包 主要是以下两个包,将其放到$GOPATH目录下

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"

二、获取docker ps 或者docker ps -a的信息代码如下

package main

import (
	"context"
	"fmt"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
)

func main() {
	//第一步:获取ctx
	ctx := context.Background()
	
	//获取cli客户端对象
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		panic(err)
	}
	//通过cli客户端对象去执行ContainerList(其实docker ps 不就是一个docker正在运行容器的一个list嘛)
	containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
	
	//下面这条命令可以获取到docker ps -a 也就是所有容器包括运行的和没有运行的
	//containers, err := cli.ContainerList(ctx, types.ContainerListOptions{All: true})
	if err != nil {
		panic(err)
	}
	
	//将获取到的结果输出
	fmt.Println("container.ID,\t\t\t\t\t\t\tcontainer.Names,    container.Created,   container.Status,    container.Ports")
	for _, container := range containers {
		fmt.Println(container.ID,container.Names,container.Created,container.Status,container.Ports)
	}
}

运行结果如下:

三、查看源码

首先来看看containers这里面到底有些啥 源码和注释如下:

type Container struct {
	ID         string   `json:"Id"` //容器id
	Names      []string //容器名称
	Image      string   //镜像名称
	ImageID    string   //镜像id
	Command    string   //命令
	Created    int64    //创建时间,时间戳,单位秒
	Ports      []Port   //端口信息
	SizeRw     int64    `json:",omitempty"`
	SizeRootFs int64    `json:",omitempty"`
	Labels     map[string]string
	State      string
	Status     string //状态,运行或者结束Exited (0)
	HostConfig struct {
		NetworkMode string `json:",omitempty"`
	}
	NetworkSettings *SummaryNetworkSettings
	Mounts          []MountPoint
}

信息还是很全面的。

来看看它是怎么获取到的,首先是ContainerList这个函数,关于ctx这个对象待会儿再说,里面其实就是解析了一下我们传入的参数,例如我上面的All : true 其实就是docker ps 对应的一些参数而已。然后通过cli的get命令获取的

// ContainerList returns the list of containers in the docker host.
func (cli *Client) ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) {
	query := url.Values{}

	if options.All {
		query.Set("all", "1")
	}

	if options.Limit != -1 {
		query.Set("limit", strconv.Itoa(options.Limit))
	}

	if options.Since != "" {
		query.Set("since", options.Since)
	}

	if options.Before != "" {
		query.Set("before", options.Before)
	}

	if options.Size {
		query.Set("size", "1")
	}

	if options.Filters.Len() > 0 {
		//nolint:staticcheck // ignore SA1019 for old code
		filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)

		if err != nil {
			return nil, err
		}

		query.Set("filters", filterJSON)
	}
	//这里就是他的数据来源,用了cli客户端的get方法,基本上所有的命令都是这种方式获取的,感觉还是使用的HTTP API
	resp, err := cli.get(ctx, "/containers/json", query, nil)
	defer ensureReaderClosed(resp)
	if err != nil {
		return nil, err
	}

	var containers []types.Container
	err = json.NewDecoder(resp.body).Decode(&containers)
	return containers, err
}

既然他的数据来自于cli.get(),那我们来看看这个方法是个啥

// get sends an http request to the docker API using the method GET with a specific Go context.
func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
	return cli.sendRequest(ctx, http.MethodGet, path, query, nil, headers)
}

和我说的一样,真的就是访问的HTTP API 看到这里基本上就能知道数据来源了。

总结

Docker的go语言的SDK基本上全是使用的HTTP API ,所以用起来他的用法基本类似,其他的也很容易看懂。

posted @ 2020-09-08 18:33  小尾学长  阅读(1645)  评论(0编辑  收藏  举报