示例说明
SDK 化的 Docker 管理让发布工具不需要拼 shell:ContainerList 的 Filters 用标签选择器圈定管辖范围——manager=deployctl 标记的容器才进入视图,误伤其他业务的容器为零。Events 接口是长连接事件流:容器启动停止等动作实时推送,Actor.Attributes 里带着容器名等元数据。
技术要点
- 标签过滤器圈定管理边界
- 单次统计快照免长连接
- 事件流实时感知容器生命周期
代码解读
NewClientWithOpts 从环境变量取连接配置并自动协商 API 版本——与不同 Docker 版本兼容。列表遍历输出名称、状态与镜像;ContainerStatsOneShot 打开一次性统计流。事件协程打印动作与名称,错误通道的循环演示错误处理占位。filtersArgs 是简化的过滤器构造辅助。
使用建议
统计流的 Body 必须关闭防句柄泄漏。事件连接断开要自动重连。生产代码直接用 filters.NewArgs 与官方辅助函数。
代码示例
package main
import (
"context"
"fmt"
"log"
"strings"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/client"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
cli, err := client.NewClientWithOpts(
client.FromEnv,
client.WithAPIVersionNegotiation(),
)
if err != nil {
log.Fatal(err)
}
defer cli.Close()
// 按标签过滤:只看本工具管理的容器
list, err := cli.ContainerList(ctx, container.ListOptions{
All: true,
Filters: filtersArgs("manager=deployctl"),
})
if err != nil {
log.Fatal(err)
}
for _, c := range list {
names := "anonymous"
if len(c.Names) > 0 {
names = c.Names[0]
}
fmt.Printf("%s state=%s image=%s\n",
names, c.State, c.Image)
stats, err := cli.ContainerStatsOneShot(ctx, c.ID)
if err == nil {
defer stats.Body.Close()
fmt.Printf(" stats stream opened for %s\n", c.ID[:12])
}
}
events, errs := cli.Events(ctx, types.EventsOptions{
Filters: filtersArgs("type=container"),
})
go func() {
for msg := range events {
fmt.Printf("event: %s %s\n",
msg.Action, msg.Actor.Attributes["name"])
}
}()
for range errs {
break // 演示:首个错误即退出事件循环
}
}
func filtersArgs(pairs ...string) filters.Args {
args := filters.NewArgs()
for _, p := range pairs {
kv := strings.SplitN(p, "=", 2)
if len(kv) == 2 {
args.Add(kv[0], kv[1])
}
}
return args
}