【云原生】利用 docker api 管理容器
目的
对容器进行管理
方案
使用 docker 官方sdk 对docker进行操作,操作依赖docker socket
官方sdk 参考 : https://docs.docker.com/engine/api/sdk/
准备工作
为了方便调试,打开docker socket 的2375端口
部分代码
定义一个docker client ,连接 docker socket
client.go
package dockermgrimport ("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
的接口
package dockermgrimport ("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 *ClientAPItype ClientAPI struct {DockerCli *client.ClientCtx context.Context
}type ClientAPIer interface {Stop(containerId string, timeout int) errorRestart(containerId string, timeout int) errorPullImage(imageUrl string) errorCreate(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (string, error)Start(containerId string, startOpts types.ContainerStartOptions) errorEnsureImageExist(image string) (bool, error)CreateNetwork(containerName string) (string, error)ConnectNetwork(networkId string, containerId string) errorRemoveImage(imageId string, removeOpt types.ImageRemoveOptions) errorStatus(containerId string) (*types.Container, error)Inspect(containerId string) (*types.ContainerJSON, error)Stats(containerId string, stream bool) (*types.ContainerStats, error)RemoveContainer(containerId string, removeVolumes bool) errorRemoveNetwork(networkId string) errorExec(containerId string, cmd []string) errorEnsureNetworkExist(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) errorExportImage(imageId string) (io.ReadCloser, error)ImportImage(savePath string, repo string, tag string) errorImageInfo(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.NetworkingConfigrspBody, 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.Seconderr := 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