文章目录
- 1 获取容器列表
- 2 查看指定容器信息
- 3. 查看容器日志
- 4 创建容器
- 4.1 简单使用
- 4.1.1 语法
- 4.1.2 完整示例
- 4.2 端口映射
- 4.2.1 语法
- 4.2.2 完整示例
- 4.3 挂载本机目录/文件
- 4.3.1 语法
- 4.3.2 完整代码
- 5. 启动容器
- 6 停止容器
- 7 删除(已停止的)容器
- 8 进入容器执行命令
- 8.1 语法
- 8.2 完整示例
1 获取容器列表
- 语法
func (cli *Client) ContainerList(ctx context.Context, options ContainerListOptions) ([]Container, error)
- 语法示例
containers, err := Cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
- 完整示例
package main
import (
"bufio"
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"io"
"log"
"os"
)
func main() {
cli, err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
err = GetContainers(cli)
if err != nil {
fmt.Println(err)
}
}
// ConnectDocker
// 链接docker
func ConnectDocker() (cli *client.Client, err error) {
cli, err = client.NewClientWithOpts(client.WithAPIVersionNegotiation(), client.WithHost("tcp://10.10.239.32:2375"))
if err != nil {
fmt.Println(err)
return nil, err
}
return cli, nil
}
// GetContainers
// 获取容器列表
func GetContainers(cli *client.Client) error {
//All-true相当于docker ps -a
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
if err != nil {
fmt.Println(err)
return err
}
for _, container := range containers {
fmt.Printf("%s %s\n", container.ID[:10], container.Image)
}
return nil
}
- 输出
docker 链接成功
08d317f408 harbocto.boe.com.cn/public/redis:4
c91fc7eeb1 harbocto.boe.com.cn/public/mysql:5.7
48bcf68112 harbocto.boe.com.cn/crow/crow-qin
381f5b2790 harbocto.boe.com.cn/magicube/ibex:0.3
2 查看指定容器信息
- 查看方法
func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ContainerJSON, error)
语法示例
ctx := context.Background()
containerJson, err := cli.ContainerInspect(ctx, containerId)
- 返回结构体
types.ContainerJSON
type ContainerJSON struct {
*ContainerJSONBase
Mounts []MountPoint
Config *Config
NetworkSettings *NetworkSettings
}
*ContainerJSONBase
的内容
type ContainerJSONBase struct {
ID string `json:"Id"`
Created string
Path string
Args []string
State *ContainerState
Image string
ResolvConfPath string
HostnamePath string
HostsPath string
LogPath string
Node *ContainerNode `json:",omitempty"`
Name string
RestartCount int
Driver string
Platform string
MountLabel string
ProcessLabel string
AppArmorProfile string
ExecIDs []string
HostConfig *HostConfig
GraphDriver GraphDriverData
SizeRw *int64 `json:",omitempty"`
SizeRootFs *int64 `json:",omitempty"`
}
- 完整示例
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
)
func main() {
cli, err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
containerId := "48bcf6811212"
containerJson, err := GetContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
fmt.Printf("=======容器信息======\nID:%+v\name:%+v\n", containerJson.ID[:10], containerJson.Name)
}
func GetContainer(cli *client.Client, containerId string) (containerInfo types.ContainerJSON, err error) {
ctx := context.Background()
containerJson, err := cli.ContainerInspect(ctx, containerId)
if err != nil {
fmt.Println(err)
return containerJson, err
}
return containerJson, nil
}
- 打印结果
docker 链接成功
=======容器信息======
ID:48bcf68112
ame:/crow-qin_crow_qin_1
3. 查看容器日志
- 语法
func (cli *Client) ContainerLogs(ctx context.Context, container string, options ContainerLogsOptions) (io.ReadCloser, error)
- 语法示例
ctx := context.Background()
logs, err := Cli.ContainerLogs(ctx, containerId, types.ContainerLogsOptions{ShowStdout: true, Follow: true})
- 参数
- ShowStdout:标准输出
- Follow:
- true:实时日志
- false:当前日志
- 完整示例
func main() {
cli, err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
err = containerLogs(cli, "48bcf68112")
if err != nil {
fmt.Println(err)
}
}
// ConnectDocker
// 链接docker
func ConnectDocker() (cli *client.Client, err error) {
cli, err = client.NewClientWithOpts(client.WithAPIVersionNegotiation(), client.WithHost("tcp://10.10.239.32:2375"))
if err != nil {
fmt.Println(err)
return nil, err
}
return cli, nil
}
//containerLogs
//获取容器日志
func containerLogs(cli *client.Client, containerId string) error {
ctx := context.Background()
logs, err := cli.ContainerLogs(ctx, containerId, types.ContainerLogsOptions{ShowStdout: true, Follow: true, ShowStderr: true})
if err != nil {
fmt.Println(err)
return err
}
_, err = io.Copy(os.Stdout, logs)
if err != nil {
fmt.Println(err)
return err
}
return nil
}
4 创建容器
4.1 简单使用
4.1.1 语法
- ContainerCreate() 函数
func (cli *Client) ContainerCreate(ctx context.Context, config *Config, hostConfig *HostConfig, networkingConfig *NetworkingConfig, platform *Platform, containerName string) (CreateResponse, error)
- 结构体
*container.Config
关于container的设置在此结构体
type Config struct {
Hostname string
Domainname string
User string
AttachStdin bool
AttachStdout bool
AttachStderr bool
ExposedPorts PortSet `json:",omitempty"`
Tty bool
OpenStdin bool
StdinOnce bool
Env []string
Cmd StrSlice
Healthcheck *HealthConfig `json:",omitempty"`
ArgsEscaped bool `json:",omitempty"`
Image string
Volumes map[string]struct{}
WorkingDir string
Entrypoint StrSlice
NetworkDisabled bool `json:",omitempty"`
MacAddress string `json:",omitempty"`
OnBuild []string
Labels map[string]string
StopSignal string `json:",omitempty"`
StopTimeout *int `json:",omitempty"`
Shell StrSlice `json:",omitempty"`
}
- 结构体
**container.HostConfig
宿主机相关配置,在这个结构体中。
type HostConfig struct {
Binds []string
ContainerIDFile string
LogConfig LogConfig
NetworkMode NetworkMode
PortBindings PortMap
RestartPolicy RestartPolicy
AutoRemove bool
VolumeDriver string
VolumesFrom []string
ConsoleSize [2]uint
CapAdd StrSlice
CapDrop StrSlice
CgroupnsMode CgroupnsMode
DNS []string `json:"Dns"`
DNSOptions []string `json:"DnsOptions"`
DNSSearch []string `json:"DnsSearch"`
ExtraHosts []string
GroupAdd []string
IpcMode IpcMode
Cgroup CgroupSpec
Links []string
OomScoreAdj int
PidMode PidMode
Privileged bool
PublishAllPorts bool
ReadonlyRootfs bool
SecurityOpt []string
StorageOpt map[string]string `json:",omitempty"`
Tmpfs map[string]string `json:",omitempty"`
UTSMode UTSMode
UsernsMode UsernsMode
ShmSize int64
Sysctls map[string]string `json:",omitempty"`
Runtime string `json:",omitempty"`
Isolation Isolation
Resources
Mounts []Mount `json:",omitempty"`
MaskedPaths []string
ReadonlyPaths []string
Init *bool `json:",omitempty"`
}
*network.NetworkingConfig
type NetworkingConfig struct {
EndpointsConfig map[string]*EndpointSettings
}
4.1.2 完整示例
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
)
func main() {
cli, err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
config := &container.Config{
Image: "harbocto.boe.com.cn/crow/crow-qin",
Tty: true,
}
//创建容器
containerId, err := CreateContainer(cli, config, nil, nil, "crow-test")
if err != nil {
fmt.Println(err)
}
//验证(用前文写的查找函数验证)
containerInfo, err := GetContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
fmt.Printf("成功创建容器%q,状态为:%q", containerInfo.ID[:10], containerInfo.State.Status)
}
// CreateContainer
// 创建容器
func CreateContainer(cli *client.Client, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (containerId string, err error) {
ctx := context.Background()
//创建容器
resp, err := cli.ContainerCreate(ctx, config, hostConfig, networkingConfig, nil, containerName)
if err != nil {
fmt.Println(err.Error())
}
return resp.ID, nil
}
- 输出
docker 链接成功
成功创建容器"c13a3deefb",状态为:"created"
4.2 端口映射
4.2.1 语法
- 容器内端口
container.Config.ExposedPorts
- 上文已经知道
container.Config
是容器的配置,它的成员ExposedPorts
即是容器内部监听的端口。 ExposedPorts
的类型是nat.PortSet
nat.PortSet
的类型如下type PortSet map[Port]struct{}
- 语法示例
config := &container.Config{ Image: "harbocto.boe.com.cn/crow/crow-qin", Tty: true, ExposedPorts: nat.PortSet{ //这里是容器内端口设置 "1840": struct{}{}, }, }
- 上文已经知道
- 绑定容器外端口
container.HostConfig.PortBindings
- 上文已经知道
container.HostConfig
是宿主机的配置 - 它的成员
PortBindings
绑定容器内外端口。 ExposedPorts
的类型是nat.PortMap
nat.PortMap
的类型如下type PortMap map[Port][]PortBinding
- 而
PortBinding
的类型如下
type PortBinding struct { HostIP string `json:"HostIp"` HostPort string }
- 语法示例
hostConfig := &container.HostConfig{ PortBindings: nat.PortMap{ "1840": []nat.PortBinding{ //容器内端口 { HostIP: "0.0.0.0", HostPort: "1841", //容器外端口 }, }, }, }
- 上文已经知道
4.2.2 完整示例
func main() {
cli, err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
//创建容器
//protMap := nat.PortSet{}
config := &container.Config{
Image: "harbocto.boe.com.cn/crow/crow-qin",
Tty: true,
ExposedPorts: nat.PortSet{
"1840": struct{}{},
},
}
hostConfig := &container.HostConfig{
PortBindings: nat.PortMap{
"1840": []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: "1841",
},
},
},
}
containerId, err := CreateContainer(cli, config, hostConfig, nil, "crow-qin-test")
err = StartContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
fmt.Println(containerId)
}
// CreateContainer
// 创建容器
func CreateContainer(cli *client.Client, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (containerId string, err error) {
ctx := context.Background()
//创建容器
resp, err := cli.ContainerCreate(ctx, config, hostConfig, networkingConfig, nil, containerName)
if err != nil {
fmt.Println(err.Error())
}
return resp.ID, nil
}
// StartContainer
// 启动容器
func StartContainer(cli *client.Client, containerId string) error {
ctx := context.Background()
err := cli.ContainerStart(ctx, containerId, types.ContainerStartOptions{})
if err != nil {
fmt.Println(err)
return err
}
return nil
}
4.3 挂载本机目录/文件
4.3.1 语法
- 指明容器内目录
container.Config.Volumes
- 类型:
Volumes map[string]struct{}
- 语法示例
config := &container.Config{ Image: "harbocto.boe.com.cn/crow/crow-qin", Tty: true, Volumes: map[string]struct{}{ "/test01": {}, }, }
- 类型:
- 容器内外路径网绑定
container.HostConfig.Binds
- 类型:[]string
- 语法示例
hostConfig := &container.HostConfig{ Binds: []string{"/tmp/liuBei.txt:/liuBei.txt"}, }
- 注意
- 如果只有
container.Config.ExposedPorts
,容器内目录将挂载到docker的默认位置(docker目录的/volumes
下) - 如果写了
container.HostConfig.PortBindings
,则container.Config.ExposedPorts
实际可以不写
- 如果只有
4.3.2 完整代码
func main() {
cli, err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
//创建容器
//protMap := nat.PortSet{}
config := &container.Config{
Image: "harbocto.boe.com.cn/crow/crow-qin",
Tty: true,
Volumes: map[string]struct{}{ //如上文,本代码这里实际可以省略
"/test01": {},
},
}
hostConfig := &container.HostConfig{
Binds: []string{"/tmp/test01:/test01"},
}
containerId, err := CreateContainer(cli, config, hostConfig, nil, "crow-qin-test")
err = StartContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
fmt.Println(containerId)
}
// CreateContainer
// 创建容器
func CreateContainer(cli *client.Client, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (containerId string, err error) {
ctx := context.Background()
//创建容器
resp, err := cli.ContainerCreate(ctx, config, hostConfig, networkingConfig, nil, containerName)
if err != nil {
fmt.Println(err.Error())
}
return resp.ID, nil
}
// StartContainer
// 启动容器
func StartContainer(cli *client.Client, containerId string) error {
ctx := context.Background()
err := cli.ContainerStart(ctx, containerId, types.ContainerStartOptions{})
if err != nil {
fmt.Println(err)
return err
}
return nil
}
5. 启动容器
- 语法
func (cli *Client) ContainerStart(ctx context.Context, containerID string, options ContainerStartOptions) error
- 语法示例
ctx := context.Background()
err := cli.ContainerStart(ctx, containerId, types.ContainerStartOptions{})
- 完整示例
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
)
func main() {
cli, err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
containerId := "c13a3deefb"
err = StartContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
//验证(用前文写的查找函数验证)
containerInfo, err := GetContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
fmt.Printf("成功启动容器%q\n状态为:%q", containerInfo.ID[:10], containerInfo.State.Status)
}
//StartContainer
// 启动容器
func StartContainer(cli *client.Client, containerId string) error {
ctx := context.Background()
err := cli.ContainerStart(ctx, containerId, types.ContainerStartOptions{})
if err != nil {
fmt.Println(err)
return err
}
return nil
}
- 输出
docker 链接成功
成功启动容器"c13a3deefb"
状态为:"running"
如上可见,我们刚才创建的容器状态从
created
变为running
6 停止容器
- 语法
func (cli *Client) ContainerStart(ctx context.Context, containerID string, options ContainerStartOptions) error
- 语法示例
ctx := context.Background()
err := cli.ContainerStart(ctx, containerId, types.ContainerStartOptions{})
- 完整示例
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
)
func main() {
cli, err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
containerId := "c13a3deefba9"
err = StopContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
//验证(用前文写的查找函数验证)
containerInfo, err := GetContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
fmt.Printf("成功停止容器%q\n状态为:%q", containerInfo.ID[:10], containerInfo.State.Status)
}
// StopContainer
// 停止容器
func StopContainer(cli *client.Client, containerId string) error {
ctx := context.Background()
err := cli.ContainerStop(ctx, containerId, container.StopOptions{})
if err != nil {
fmt.Println(err)
return err
}
return nil
}
7 删除(已停止的)容器
- 语法
func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options ContainerRemoveOptions) error
- 语法示例
ctx := context.Background()
err := cli.ContainerRemove(ctx, containerId, types.ContainerRemoveOptions{})
- 完整示例
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
)
func main() {
cli, err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
containerId := "c13a3deefba9"
err = DeleteContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
//验证(用前文写的查找函数验证)
b, err := CheckContainer(cli, containerId)
if err != nil {
fmt.Println(err)
}
if b == false {
fmt.Println("删除成功")
} else {
fmt.Println("删除失败")
}
}
// DeleteContainer
// 删除已停止容器
func DeleteContainer(cli *client.Client, containerId string) error {
ctx := context.Background()
err := cli.ContainerRemove(ctx, containerId, types.ContainerRemoveOptions{})
if err != nil {
fmt.Println(err)
return err
}
return nil
}
// CheckContainer
// 获取容器信息
func CheckContainer(cli *client.Client, containerId string) (result bool, err error) {
ctx := context.Background()
containerJson, err := cli.ContainerInspect(ctx, containerId)
if err != nil {
fmt.Println(err)
return false, err
}
if containerJson.ContainerJSONBase == nil {
return false,nil
}
fmt.Println(containerJson)
return true, nil
}
8 进入容器执行命令
本文仅演示示例,实际应用参见本人文档《gin框架使用websocket实现进入容器内部执行命令》
8.1 语法
- 创建配置
说明:创建一个新的exec配置来运行exec进程。
func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config ExecConfig) (IDResponse, error)
语法示例
ir, err := dockerCli.ContainerExecCreate(ctx, containerId, types.ExecConfig{
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
Cmd: []string{"/bin/sh"},
Tty: true,
})
- 将链接附加到exec进程
语法
func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config ExecStartCheck) (HijackedResponse, error)
语法示例
hr, err := cli.ContainerExecAttach(ctx, ir.ID, types.ExecStartCheck{Detach: false, Tty: true})
- 命令传入
_, err = hr.Conn.Write([]byte("ls\r"))
8.2 完整示例
- 代码
package main
import (
"bufio"
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"io"
"log"
"os"
)
func main() {
cli,err := ConnectDocker()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("docker 链接成功")
}
//GetContainers()
err = ExecContainer(cli,"48bcf68112")
if err != nil {
fmt.Println(err)
}
}
// ConnectDocker
// 链接docker
func ConnectDocker() (cli *client.Client,err error) {
cli, err = client.NewClientWithOpts(client.WithAPIVersionNegotiation(), client.WithHost("tcp://10.10.239.32:2375"))
if err != nil {
fmt.Println(err)
return nil,err
}
return cli,nil
}
func ExecContainer(cli *client.Client, containerId string) error {
ctx := context.Background()
//创建进程
ir, err := cli.ContainerExecCreate(ctx, containerId, types.ExecConfig{
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
Cmd: []string{"/bin/sh"},
Tty: true,
})
if err != nil {
return err
}
// 将链接附加到exec进程
hr, err := cli.ContainerExecAttach(ctx, ir.ID, types.ExecStartCheck{Detach: false, Tty: true})
if err != nil {
return err
}
// 关闭链接和读取器
defer hr.Close()
// 输入一条命令
_, err = hr.Conn.Write([]byte("echo liuBei > xiShu.txt\r"))
if err != nil {
return err
}
//输入第二条命令
_, err = hr.Conn.Write([]byte("cat xiShu.txt\r"))
if err != nil {
return err
}
//输出
scanner := bufio.NewScanner(hr.Conn)
for scanner.Scan() {
fmt.Println(scanner.Text())
if err != nil {
log.Println("写入错误", err)
continue
}
}
return nil
}
- 结果输出
docker 链接成功
/ # echo liuBei > xiShu.txt
/ # cat xiShu.txt
liuBei