【云原生】利用 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

相关推荐
SXJR7 分钟前
使用docker 部署向量数据库Milvus
数据库·docker·容器·milvus·向量数据库
这个DBA有点耶12 分钟前
时序数据库深度对比:2026 年主流 TSDB 架构演进与选型指南
数据库·sql·云原生·架构·运维开发·时序数据库
qq_4523962318 分钟前
第二篇:《K8s 集群搭建:Minikube、kubeadm、Kind 对比与实操》
容器·kubernetes·kind
jingqiulyue1 小时前
docker run出现exited或者不断restart怎么办
docker·容器
小哈里1 小时前
【K8S】OCI标准下的企业级镜像治理:Harbor+Skopeo+Trivy 最佳实践
云原生·容器·kubernetes·harbor·镜像·skopen
花间相见1 小时前
【Kubernetes02】—— 使用 kubeadm 从零搭建 K8s 集群(实操避坑版)
云原生·容器·kubernetes
人工智能培训1 小时前
从GPT到开源大模型
人工智能·gpt·深度学习·机器学习·容器·知识图谱
张小凡vip2 小时前
Kubernetes--secret的简介和使用
云原生·容器·kubernetes
IT策士2 小时前
Docker 常见面试问题
docker·容器·面试
预测模型的开发与应用研究3 小时前
双Docker Oracle XE 跨库查询操作文档
docker·oracle·容器