在命令行中我們可以通過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 ,所以用起來他的用法基本類似,其他的也很容易看懂。