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 ,所以用起来他的用法基本类似,其他的也很容易看懂。