基于golang操作Docker

官方库

github.com/docker/docker

  • github.com/docker/docker/api/types
  • github.com/docker/docker/client
  • github.com/docker/docker/api/types/container
  • github.com/docker/docker/pkg/stdcopy

官方文档

https://docs.docker.com/engine/api/sdk

实例: https://docs.docker.com/engine/api/sdk/examples/

docker 开启远程访问

vim /usr/lib/systemd/system/docker.service

在[Service]部分,修改ExecStart参数,在最后增加-H tcp://0.0.0.0:2375

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375
systemctl daemon-reload && systemctl restart docker
  1. 查看是否成功 curl http://localhost:2375/version

如果不能访问,可能是因为防火墙的原因,所以开放防火墙2357端口

firewall-cmd --zone=public --add-port=2375/tcp --permanent
firewall-cmd --r

Docker开启远程安全访问 请参考 https://blog.csdn.net/yuntiank/article/details/116520114

Docker 开启远程安全访问(脚本生成配置) 请参考 https://blog.csdn.net/cszzboy/article/details/123552589

实例

package main

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"io"
	"log"
	"os"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
	"github.com/docker/docker/pkg/stdcopy"
)

func main(){
	case1()

	case2()

	case3()

	case4()

	case5()
}

// docker 客户端
func Client() *client.Client {
	// 获取docker镜像列表
	//cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) // 连接本地的docker

	// 连接 开启了远程访问的docker
	cli, err := client.NewClientWithOpts(client.WithHost("tcp://192.168.0.9:2375"), client.WithAPIVersionNegotiation())

	// 连接 开启了远程访问的docker, 旧方法,已经弃用
	//cli, err := client.NewClient("tcp://127.0.0.1:2375", "1.40", nil, nil)
	if err != nil {
		log.Println(err)
		os.Exit(0)
	}
	return cli
}

// docker image ls
func case1(){
	cli := Client()
	images, err := cli.ImageList(context.Background(), types.ImageListOptions{})
	if err != nil {
		log.Println(err)
		os.Exit(0)
	}
	var imagesLib []string
	for _, image := range images {
		log.Println("image = ", image)
		log.Println("_______________\n\n")
		imagesLib = append(imagesLib, image.RepoTags[0])
	}
	log.Println(imagesLib)
}

// docker ps
func case2(){
	cli := Client()
	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
	if err != nil {
		panic(err)
	}

	for _, container := range containers {
		log.Print("container = ", container)
		log.Println("_______________\n\n")
		// 停止所有容器
		//if err := cli.ContainerStop(context.Background(), container.ID, nil); err != nil {
		//	panic(err)
		//}
	}
}

// 运行一个容器
// docker run
func case3(){
	cli := Client()
	// 拉镜像
	reader, err := cli.ImagePull(context.Background(), "docker.io/library/alpine", types.ImagePullOptions{})
	if err != nil {
		panic(err)
	}

	defer reader.Close()
	io.Copy(os.Stdout, reader)


	/*
	container.Config:
		Hostname        string              // 主机名
		Domainname      string              // 域名
		User            string              // 将在容器内运行命令的用户,还支持User:group
		AttachStdin     bool                // 附加标准输入,实现用户交互
		AttachStdout    bool                // 附加标准输出
		AttachStderr    bool                // 附加标准误差
		ExposedPorts    nat.PortSet         `json:",omitempty"` //暴露端口列表
		Tty             bool                // 将标准流附加到Tty,如果Tty未关闭,则包括stdin。
		OpenStdin       bool                // Open stdin
		StdinOnce       bool                // 如果为true,请在连接的1个客户端断开连接后关闭stdin。
		Env             []string            // 要在容器中设置的环境变量列表
		Cmd             strslice.StrSlice   // 启动容器时要运行的命令
		Healthcheck     *HealthConfig       `json:",omitempty"` // Healthcheck描述了如何检查容器是否健康
		ArgsEscaped     bool                `json:",omitempty"` // True,如果命令已转义(意味着将其视为命令行)(特定于Windows)。
		Image           string              // 操作传递的镜像的名称(例如,可以是符号)
		Volumes         map[string]struct{} // 用于容器的卷(装载)列表
		WorkingDir      string              // 将启动命令中的当前目录(PWD)
		Entrypoint      strslice.StrSlice   // 启动容器时要运行的入口点
		NetworkDisabled bool                `json:",omitempty"` // 已禁用网络
		MacAddress      string              `json:",omitempty"` // 容器的Mac地址
		OnBuild         []string            // image Dockerfile上定义的OnBuild元数据
		Labels          map[string]string   // 设置到此容器的标签列表
		StopSignal      string              `json:",omitempty"` // 停止容器的信号
		StopTimeout     *int                `json:",omitempty"` // 停止容器的超时(秒)
		Shell           strslice.StrSlice   `json:",omitempty"` // Shell表示RUN的Shell形式,CMD,ENTRYPOINT
	 */

	/*
	container.HostConfig:
		Binds           []string      // 此容器的卷绑定列表
		ContainerIDFile string        // 写入containerId的文件(路径)
		LogConfig       LogConfig     // 此容器的日志配置
		NetworkMode     NetworkMode   // 用于容器的网络模式
		PortBindings    nat.PortMap   // 暴露端口(容器)和主机之间的端口映射
		RestartPolicy   RestartPolicy // 用于容器的重新启动策略
		AutoRemove      bool          // 退出时自动删除容器
		VolumeDriver    string        // 用于装载卷的卷驱动程序的名称
		VolumesFrom     []string      // 从其他容器获取的卷列表

		// Applicable to UNIX platforms
		CapAdd          strslice.StrSlice // 要添加到容器的内核功能列表
		CapDrop         strslice.StrSlice // 要从容器中删除的内核功能列表
		CgroupnsMode    CgroupnsMode      // 用于容器的Cgroup命名空间模式
		DNS             []string          `json:"Dns"`        // 要查找的DNS服务器列表
		DNSOptions      []string          `json:"DnsOptions"` // 要查找的DNS选项列表
		DNSSearch       []string          `json:"DnsSearch"`  // 要查找的DNS搜索列表
		ExtraHosts      []string          // 额外主机列表
		GroupAdd        []string          // 容器进程将作为其运行的其他组的列表
		IpcMode         IpcMode           // 用于容器的IPC命名空间
		Cgroup          CgroupSpec        // 用于容器的Cgroup
		Links           []string          // 链接列表(名称:alias form)
		OomScoreAdj     int               // OOM-killing的容器偏好
		PidMode         PidMode           // 用于容器的PID命名空间
		Privileged      bool              // 容器是否处于特权模式
		PublishAllPorts bool              // docker是否应该发布容器的所有暴露端口
		ReadonlyRootfs  bool              // 容器根文件系统是只读的吗
		SecurityOpt     []string          // 用于自定义MLS系统(如SELinux)标签的字符串值列表。
		StorageOpt      map[string]string `json:",omitempty"` // 每个容器的存储驱动程序选项。
		Tmpfs           map[string]string `json:",omitempty"` // 用于集装箱的tmpfs(支架)列表
		UTSMode         UTSMode           // 用于容器的UTS命名空间
		UsernsMode      UsernsMode        // 用于容器的用户命名空间
		ShmSize         int64             // shm内存使用总量
		Sysctls         map[string]string `json:",omitempty"` // 用于容器的命名空间sysctl列表
		Runtime         string            `json:",omitempty"` // 与此容器一起使用的运行时

		// Applicable to Windows
		ConsoleSize [2]uint   // 初始控制台尺寸(高度、宽度)
		Isolation   Isolation // 容器的隔离技术(例如默认、hyperv)

		// 包含容器的资源(cgroup、ulimit)
		Resources

		// 安装容器使用的规格
		Mounts []mount.Mount `json:",omitempty"`

		// MaskedPaths是容器内要屏蔽的路径列表(这将覆盖默认路径集)
		MaskedPaths []string

		// ReadonlyPaths是要在容器内设置为只读的路径列表(这将覆盖默认路径集)
		ReadonlyPaths []string

		// 在容器内运行自定义init,如果为null,则使用守护进程的配置设置
		Init *bool `json:",omitempty"`
	 */

	/*
	network.NetworkingConfig:
		EndpointsConfig map[string]*EndpointSettings // 为每个连接网络配置端点
	 */

	/*
	specs.Platform:
		// 架构字段指定CPU架构,例如
		// `amd64` or `ppc64`.
		Architecture string `json:"architecture"`

		// 操作系统指定操作系统,例如“linux”或“windows”。
		OS string `json:"os"`

		// OSVersion是一个可选字段,用于指定操作系统
		// 版本,例如在Windows“10.0.14393.1066”上。
		OSVersion string `json:"os.version,omitempty"`

		// OSFeatures是一个可选字段,用于指定字符串数组,
		// 每个都列出了所需的操作系统功能(例如在Windows“win32k”上).
		OSFeatures []string `json:"os.features,omitempty"`

		// 变量是一个可选字段,用于指定CPU的变量
		// 示例“v7”用于在体系结构为“arm”时指定ARMv7。
		Variant string `json:"variant,omitempty"`
	 */

	// 创建容器
	resp, err := cli.ContainerCreate(context.Background(), &container.Config{
		Image: "alpine",
		Cmd:   []string{"echo", "hello world"},
		Tty:   false,
	}, nil, nil, nil, "")
	if err != nil {
		panic(err)
	}

	// 启动容器
	if err := cli.ContainerStart(context.Background(), resp.ID, types.ContainerStartOptions{}); err != nil {
		panic(err)
	}

	// 监听容器状态
	statusCh, errCh := cli.ContainerWait(context.Background(), resp.ID, container.WaitConditionNotRunning)
	select {
	case err := <-errCh:
		if err != nil {
			panic(err)
		}
	case <-statusCh:
	}

	// 获取容器日志
	out, err := cli.ContainerLogs(context.Background(), resp.ID, types.ContainerLogsOptions{ShowStdout: true})
	if err != nil {
		panic(err)
	}

	stdcopy.StdCopy(os.Stdout, os.Stderr, out)
}

// docker pull
// 通过身份验证拉取图像
func case4(){
	cli := Client()
	authConfig := types.AuthConfig{
		Username: "username",
		Password: "password",
	}
	encodedJSON, err := json.Marshal(authConfig)
	if err != nil {
		panic(err)
	}
	authStr := base64.URLEncoding.EncodeToString(encodedJSON)

	out, err := cli.ImagePull(context.Background(), "alpine", types.ImagePullOptions{RegistryAuth: authStr})
	if err != nil {
		panic(err)
	}

	defer out.Close()
	io.Copy(os.Stdout, out)
}

// docker push
func case5(){
	cli := Client()
	createResp, err := cli.ContainerCreate(context.Background(), &container.Config{
		Image: "alpine",
		Cmd:   []string{"touch", "/helloworld"},
	}, nil, nil, nil, "")
	if err != nil {
		panic(err)
	}

	if err := cli.ContainerStart(context.Background(), createResp.ID, types.ContainerStartOptions{}); err != nil {
		panic(err)
	}

	statusCh, errCh := cli.ContainerWait(context.Background(), createResp.ID, container.WaitConditionNotRunning)
	select {
	case err := <-errCh:
		if err != nil {
			panic(err)
		}
	case <-statusCh:
	}

	commitResp, err := cli.ContainerCommit(context.Background(), createResp.ID, types.ContainerCommitOptions{Reference: "helloworld"})
	if err != nil {
		panic(err)
	}

	log.Println(commitResp.ID)
}

// 远程 ssh连接
// 如果有报错 exec /usr/lib/ssh/ssh-askpass : No such file or directory error.
// 安装 ssh-askpass
//		sudo apt-get autoremove openssh-client
//		sudo apt-get install openssh-client openssh-sftp-server openssh-server ssh
//		sudo apt-get install ssh-askpass
func case6(){
	helper, err := connhelper.GetConnectionHelper("ssh://root@192.168.0.192:22")
	if err != nil {
		log.Println(err)
		return
	}
	httpClient := &http.Client{
		Transport: &http.Transport{
			DialContext: helper.Dialer,
		},
	}
	cl, err := client.NewClientWithOpts(
		client.WithHTTPClient(httpClient),
		client.WithHost(helper.Host),
		client.WithDialContext(helper.Dialer),
	)
	if err != nil {
		log.Println("Unable to create docker client")
		panic(err)
	}

	log.Println(cl.ImageList(context.Background(), types.ImageListOptions{}))
}


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值