【云原生】利用 docker api 管理容器

目的

对容器进行管理

方案

使用 docker 官方sdk 对docker进行操作,操作依赖docker socket

官方sdk 参考 : https://docs.docker.com/engine/api/sdk/

准备工作

为了方便调试,打开docker socket 的2375端口

部分代码

定义一个docker client ,连接 docker socket

client.go

go 复制代码
package dockermgr

import (
	"context"
	"github.com/docker/docker/client"
	"log"
	"net"
)

func DockerClient(apiVersion string) *client.Client {
	if apiVersion == "" {
		apiVersion = "1.39"
	}
	dockerClient, err := client.NewClientWithOpts(
		//client.WithHost("tcp://192.168.124.84:2375"),
		client.WithDialContext(func(_ context.Context, _, _ string) (net.Conn, error) {
			return net.Dial("unix", "/var/run/docker.sock")
		}),
		client.WithVersion(apiVersion))
	if err != nil {
		log.Fatal(err)
	}
	ping, err := dockerClient.Ping(context.Background())
	//}))
	if err != nil {
		log.Fatal(err)
	}
	log.Println(ping.APIVersion)
	return dockerClient
}

container.go

主要用来管理容器

这里定义了一个ClientAPI的结构体以及一个ClientAPIer的接口

go 复制代码
package dockermgr

import (
	"context"
	"errors"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/client"
	"io"
	"net/http"
	"os"
	"strings"
)

var c *ClientAPI

type ClientAPI struct {
	DockerCli *client.Client
	Ctx       context.Context
}

type ClientAPIer interface {
	Stop(containerId string, timeout int) error
	Restart(containerId string, timeout int) error
	PullImage(imageUrl string) error
	Create(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (string, error)
	Start(containerId string, startOpts types.ContainerStartOptions) error
	EnsureImageExist(image string) (bool, error)
	CreateNetwork(containerName string) (string, error)
	ConnectNetwork(networkId string, containerId string) error
	RemoveImage(imageId string, removeOpt types.ImageRemoveOptions) error
	Status(containerId string) (*types.Container, error)
	Inspect(containerId string) (*types.ContainerJSON, error)
	Stats(containerId string, stream bool) (*types.ContainerStats, error)
	RemoveContainer(containerId string, removeVolumes bool) error
	RemoveNetwork(networkId string) error
	Exec(containerId string, cmd []string) error
	EnsureNetworkExist(networkName string) (string, error)
	FindContainer(containerName string) (string, error)
	IsImageUsed(imageID string) (bool, error)
	ContainerLogs(writer http.ResponseWriter, containerId string, follow bool, since string, tail string, until string) error
	ExportImage(imageId string) (io.ReadCloser, error)
	ImportImage(savePath string, repo string, tag string) error
	ImageInfo(imageId string) (*types.ImageInspect, error)
}

func GetContainerAPIer() ClientAPIer {
	return c
}

func NewContainerMgr(apiVersion string) ClientAPIer {
	return &ClientAPI{
		DockerCli: DockerClient(apiVersion),
		Ctx:       context.Background(),
	}
}

func (c *ClientAPI) Create(config *container.Config, hostConfig *container.HostConfig, networkConfig *network.NetworkingConfig, containerName string) (string, error) {
	//var networkConfig *network.NetworkingConfig

	rspBody, err := c.DockerCli.ContainerCreate(c.Ctx, config, hostConfig, networkConfig, nil, containerName)
	if err != nil {
		return "", err
	}
	return rspBody.ID, nil
}

func (c *ClientAPI) Start(containerId string, startOpts types.ContainerStartOptions) error {
	err := c.DockerCli.ContainerStart(c.Ctx, containerId, startOpts)
	if err != nil {
		return err
	}
	return nil
}

func (c *ClientAPI) Status(containerId string) (*types.Container, error) {
	var args = filters.NewArgs()
	args.Add("id", containerId)
	containerInfo, err := c.DockerCli.ContainerList(c.Ctx, types.ContainerListOptions{
		All:     true,
		Filters: args})

	if err != nil {
		return nil, err
	}
	if len(containerInfo) > 0 {
		return &containerInfo[0], nil
	}
	return nil, errors.New("not found container")
}

func (c *ClientAPI) Inspect(containerId string) (*types.ContainerJSON, error) {
	containerInpsect, err := c.DockerCli.ContainerInspect(c.Ctx, containerId)
	if err != nil {
		return nil, err
	}
	return &containerInpsect, nil
}

func (c *ClientAPI) Stats(containerId string, stream bool) (*types.ContainerStats, error) {
	containerStats, err := c.DockerCli.ContainerStats(c.Ctx, containerId, stream)
	if err != nil {
		return nil, err
	}
	return &containerStats, nil
}

func (c *ClientAPI) Stop(containerId string, timeout int) error {
	if timeout == 0 {
		timeout = 10
	}
	options := container.StopOptions{
		Signal:  "",
		Timeout: &timeout,
	}

	err := c.DockerCli.ContainerStop(c.Ctx, containerId, options)

	if err != nil {
		return err
	}
	return nil
}

func (c *ClientAPI) Restart(containerId string, timeout int) error {
	if timeout == 0 {
		timeout = 10
	}
	options := container.StopOptions{
		Signal:  "",
		Timeout: &timeout,
	}

	err := c.DockerCli.ContainerRestart(c.Ctx, containerId, options)

	if err != nil {
		return err
	}
	return nil
}

func (c *ClientAPI) RemoveContainer(containerId string, removeVolumes bool) error {
	//var duration = 10 * time.Second

	err := c.DockerCli.ContainerRemove(c.Ctx, containerId, types.ContainerRemoveOptions{RemoveVolumes: removeVolumes})

	if err != nil {
		return err
	}
	return nil
}

func (c *ClientAPI) Exec(containerId string, cmd []string) error {
	execId, err := c.DockerCli.ContainerExecCreate(c.Ctx, containerId, types.ExecConfig{
		Cmd: cmd,
	})
	if err != nil {
		return err
	}
	//err = c.DockerCli.ContainerExecStart(c.Ctx, execId.ID, types.ExecStartCheck{
	//	Detach: false,
	//	Tty:    false,
	//})
	//if err != nil {
	//	return err
	//}
	resp, err := c.DockerCli.ContainerExecAttach(c.Ctx, execId.ID, types.ExecStartCheck{
		Detach: false,
		Tty:    false,
	})
	defer resp.Close()
	io.Copy(os.Stdout, resp.Reader)
	if err != nil {
		return err
	}

	return nil
}

func (c *ClientAPI) FindContainer(containerName string) (string, error) {
	var args = filters.NewArgs()
	args.Add("name", containerName)
	containerInfos, err := c.DockerCli.ContainerList(c.Ctx, types.ContainerListOptions{
		All:     true,
		Filters: args})

	if err != nil {
		return "", err
	}
	if len(containerInfos) > 0 {
		for i, ci := range containerInfos {
			if strings.TrimLeft(ci.Names[0], "/") == containerName {
				return containerInfos[i].ID, nil
			}
		}
	}
	return "", nil
}

func (c *ClientAPI) ContainerLogs(writer http.ResponseWriter, containerId string, follow bool, since string, tail string, until string) error {
	options := types.ContainerLogsOptions{
		ShowStdout: true,
		ShowStderr: true,
		Since:      since,
		Until:      until,
		Timestamps: false,
		Follow:     follow,
		Tail:       tail,
		Details:    false,
	}
	responseBody, err := c.DockerCli.ContainerLogs(c.Ctx, containerId, options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	writer.Header().Add("Content-Type", "application/octet-stream")
	writer.WriteHeader(200)
	_, err = io.Copy(writer, responseBody)
	return err
}

其他更多的代码内容,请参考我的github

我的Github

相关推荐
小锋学长生活大爆炸22 分钟前
【教程】在Docker中部署Hermes Agent
docker·容器·agent·教程·工具·openclaw·hermes
AI服务老曹8 小时前
异构计算时代的安防底座:基于 Docker 的 X86/ARM 双模部署与 NPU 资源池化实战
arm开发·docker·容器
筱顾大牛10 小时前
使用docker部署到服务器
docker·部署
UIUV11 小时前
Go语言入门到精通学习笔记
后端·go·编程语言
another heaven13 小时前
【Docker/虚拟机 深度对比Docker与虚拟机:原理、区别与最佳使用场景】
运维·docker·容器
独自归家的兔13 小时前
2026年4月16日 Ubuntu系统 Docker 的安装与配置
运维·docker·容器
舒一笑14 小时前
Docker 离线镜像导入后变成 <none>:<none>?一文讲透原因、排查与正确打包姿势
后端·docker·容器
匀泪14 小时前
云原生(Kubernetes service微服务)
微服务·云原生·kubernetes
littleschemer14 小时前
Go异步持久化如何防止炸服
go·map并发崩溃
Bonnienienie14 小时前
服务器Docker实例化容器 -- 踩坑大全
docker