当前位置:   article > 正文

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

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())
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

简单的创建个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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

容器启动

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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

容器停止

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

容器单独执行另外的命令

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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

删除容器

func (s *Container) Close() error {
	err := s.Stop()
	if err == nil {
		err = cli.ContainerRemove(context.Background(), s.Id, container.RemoveOptions{})
	}
	return err
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

完整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
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

这里容器客户端基本功能结构体就已经构建好了,测试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函数就行了,地址短口填对

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/196882
推荐阅读
相关标签
  

闽ICP备14008679号