go docker sdk使用第一章----入门

go docker sdk使用第一章----入门

golang docker sdk 需要和安装的docker api version相兼容。一般我们只需要注意docker api version就可以了.
docker version 查看本地docker api version
在这里插入图片描述
go get github.com/docker/docker/client 拉取docker client sdk

go 代码中得创一个docker client。后面和docker 所有操作都走这个client,你甚至能创几个来自不同机器的client,在程序内控制几台机器的docker

import ( 
	"github.com/docker/docker/client"
	"log"
)
var cli *client.Client
func init() {
	var err error
	cli, err = client.NewClientWithOpts(client.WithVersion("1.39"), client.WithAPIVersionNegotiation())//初始化一个本地的docker client,我docker version 命令行输出中api version 是1.39所以这里是1.39
	if err != nil {
		log.Fatalln("init docker client failed " + err.Error())
	}
}

简单的创建个debian镜像的容器

type Container struct {
	Id string
}
//指定工作目录(如果没有指定,你容器的默认目录绝对路径为/),Cmd是你容器启动时的命令,我这里启动的是我自己一个简单的echo服务,这里你可以替换成你自己的。
//HostConfig 这里如果你没什么额外操作直接nil,这里我是将容器的container 的/root目录与宿主机当前目录下的container目录链接了一起。就可以启动一个纯debian镜像的容器,在里面跑我宿主机上的程序
//Tty选项 如果容器启动的程序没有标准输出输入直接写入到文件的话,可以不写默认是false。如果启动tty,attchstdin/stderr/stdout这三个选项根据自身需求打开
func NewContainerWithLink(container_name, docker_filepath, host_path string) (*Container, error) {
	resp, err := cli.ContainerCreate(context.Background(), &container.Config{Image: "debian", WorkingDir: "/root", Cmd: []string{"./child"}, Tty: true, AttachStdout: true, AttachStderr: true}, &container.HostConfig{Mounts: []mount.Mount{mount.Mount{Type: mount.TypeBind, Source: host_path, Target: docker_filepath, BindOptions: &mount.BindOptions{CreateMountpoint: true}}}}, nil, nil, container_name)
	// return nil, err
	if err == nil {
		return &Container{Id: resp.ID}, nil
	}
	return nil, err
}

容器启动

func (s *Container) Run() error {
	err := cli.ContainerStart(context.Background(), s.Id, container.StartOptions{})
	if err != nil {
		return err
	}
	//attach 能将容器的实时stdin,stdout,stderr暴露出来,上面创建时你开了stdin的话就能通过暴露出来的Conn给把数据写入容器
	hresp, err := cli.ContainerAttach(context.Background(), s.Id, container.AttachOptions{Stream: true, Stdout: true, Stderr: true})
	if err != nil {
		return err
	}
	go func() {
		_, err2 := io.Copy(os.Stdout, hresp.Conn)
		if err2 != nil {
			fmt.Fprintln(os.Stderr, err2.Error())
		}
	}()
	// var resp io.ReadCloser
	return nil
}

容器停止

func (s *Container) Stop() error {
	return cli.ContainerStop(context.Background(), s.Id, container.StopOptions{Signal: "SIGQUIT"})
}

容器单独执行另外的命令

func (s *Container) Exec(cmd string, args ...string) error {
	cmds := make([]string, 1+len(args))
	cmds[0] = cmd
	if len(args) > 0 {
		copy(cmds[1:], args)
	}
	ex, err := cli.ContainerExecCreate(context.Background(), s.Id, types.ExecConfig{Tty: true, AttachStdout: true, AttachStderr: true, Detach: true, Cmd: cmds})
	if err == nil {
		err = cli.ContainerExecStart(context.Background(), ex.ID, types.ExecStartCheck{Detach: true, Tty: true})
	}
	return err
}

删除容器

func (s *Container) Close() error {
	err := s.Stop()
	if err == nil {
		err = cli.ContainerRemove(context.Background(), s.Id, container.RemoveOptions{})
	}
	return err
}

完整demo代码

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"os"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/mount"
	"github.com/docker/docker/client"
)

var (
	cli *client.Client
)

func init() {
	var err error
	cli, err = client.NewClientWithOpts(client.WithVersion("1.39"), client.WithAPIVersionNegotiation())
	if err != nil {
		log.Fatalln("init docker client failed " + err.Error())
	}
}

type Container struct {
	Id string
}

func NewContainerWithLink(container_name, docker_filepath, host_path string) (*Container, error) {
	resp, err := cli.ContainerCreate(context.Background(), &container.Config{Image: "debian", WorkingDir: "/root", Cmd: []string{"./child"}, Tty: true, AttachStdout: true, AttachStderr: true}, &container.HostConfig{Mounts: []mount.Mount{mount.Mount{Type: mount.TypeBind, Source: host_path, Target: docker_filepath, BindOptions: &mount.BindOptions{CreateMountpoint: true}}}}, nil, nil, container_name)
	// return nil, err
	if err == nil {
		return &Container{Id: resp.ID}, nil
	}
	return nil, err
}
func (s *Container) Stop() error {
	return cli.ContainerStop(context.Background(), s.Id, container.StopOptions{Signal: "SIGQUIT"})
}
func (s *Container) Close() error {
	err := s.Stop()
	if err == nil {
		err = cli.ContainerRemove(context.Background(), s.Id, container.RemoveOptions{})
	}
	return err
}

func (s *Container) Run() error {
	err := cli.ContainerStart(context.Background(), s.Id, container.StartOptions{})
	if err != nil {
		return err
	}
	hresp, err := cli.ContainerAttach(context.Background(), s.Id, container.AttachOptions{Stream: true, Stdout: true, Stderr: true})
	if err != nil {
		return err
	}
	go func() {
		_, err2 := io.Copy(os.Stdout, hresp.Conn)
		if err2 != nil {
			fmt.Fprintln(os.Stderr, err2.Error())
		}
	}()
	// var resp io.ReadCloser
	return nil
}
func (s *Container) Exec(cmd string, args ...string) error {
	cmds := make([]string, 1+len(args))
	cmds[0] = cmd
	if len(args) > 0 {
		copy(cmds[1:], args)
	}
	ex, err := cli.ContainerExecCreate(context.Background(), s.Id, types.ExecConfig{Tty: true, AttachStdout: true, AttachStderr: true, Detach: true, Cmd: cmds})
	if err == nil {
		err = cli.ContainerExecStart(context.Background(), ex.ID, types.ExecStartCheck{Detach: true, Tty: true})
		if err == nil {
			var r io.ReadCloser
			r, err = cli.ContainerLogs(context.Background(), s.Id, container.LogsOptions{ShowStdout: true})
			if err == nil {
				_, err = io.Copy(os.Stdout, r)
				if err == io.EOF {
					err = nil
				}
			}
		}
	}
	return err
}

这里容器客户端基本功能结构体就已经构建好了,测试main函数由你自行编写,边学边写效率才能更高,不然一切都是纸上谈兵。运行目录下container目录与容器/root目录相关联。测试程序自行拷贝到container 目录下即可。
我自己的demo 效果
在这里插入图片描述

docker服务 tcp外部访问开启

如果你使用的是linux包管理工具安装的docker,你需要找到启动你docker服务的地方,一般是走systemd管理的。直接systemctl status docker就可以看见docker.service文件位置在哪里,默认是监听unix socket docker.sock来访问的。默认配置启动命令那里参数应该是/..../dockerd -H fd:// 你在后面加一个-H tcp://你要监听的ip地址:端口号。然后systemctl daemon-reload,docker sdk在使用client.NewClientWithOpts函数时,里面是加一个client.WithHost函数就行了,地址短口填对

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值