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

相关推荐
慌糖4 小时前
微服务介绍
微服务·云原生·架构
风飘百里9 小时前
Go CGo 权威指南:从『链接地狱』到『部署天堂』
go
nlog3n9 小时前
基于 govaluate 的监控系统中,如何设计灵活可扩展的自定义表达式函数体系
算法·go
高山莫衣9 小时前
Docker Desktop导致存储空间不足时的解决方案
docker·容器·eureka
鹏大师运维9 小时前
在银河麒麟V10 SP1上手动安装与配置高版本Docker的完整指南
linux·运维·docker·容器·麒麟·统信uos·中科方德
lovely_nn9 小时前
docker 介绍
docker·k8s
Ahlson9 小时前
【fnNAS】docker的nginx配置html
nginx·docker·容器·fnnas
LuckyLay10 小时前
Compose 常用命令详解——AI教你学Docker
docker·容器·eureka
阿里云云原生10 小时前
阿里云可观测 2025 年 6 月产品动态
云原生
阿里云云原生10 小时前
30 秒锁定黑客攻击:SLS SQL 如何从海量乱序日志中“揪”出攻击源
云原生