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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM