【Golang】golang使用三方SDK操作容器指南
【Golang】golang使用三方SDK操作容器指南
大家好 我是寸铁👊
总结了一篇 golang使用三方SDK操作容器✨
喜欢的小伙伴可以点点关注 💝
这应该是目前全网最全golang使用三方SDK操作容器的指南了✌️
CreateConfig
主要是创建容器的配置信息,常用的字段
使用包如下:
"github.com/docker/docker/api/types"
配置创建Docker 容器的结构体,具体字段的含义和用途如下:
1.Hostname: 容器的主机名。
2.Domainname: 容器的域名。
3.User: 执行容器内命令的用户,也支持指定用户和用户组。
4.AttachStdin: 是否连接标准输入,使得用户可以与容器进行交互。
5.AttachStdout: 是否连接标准输出。
6.AttachStderr: 是否连接标准错误输出。
7.ExposedPorts: 用于指定容器暴露的端口,是一个 nat.PortSet 类型的字段。
8.Tty: 是否将标准流连接到 tty(终端),包括标准输入(如果它没有关闭的话)。
9.OpenStdin: 是否打开标准输入。
10.StdinOnce: 如果为 true,在第一个连接的客户端断开连接后关闭标准输入。
11.Env: 设置在容器中使用的环境变量的列表。
12.Cmd: 在启动容器时运行的命令。
13.Healthcheck: 描述容器健康状况检查的配置。
14.ArgsEscaped: 如果为 true,表示命令已经被转义,即将其视为命令行(特定于 Windows)。
15.Image: 由操作者传递的镜像的名称。
16.Volumes: 用于指定容器使用的卷(挂载)的列表。
17.WorkingDir: 容器中命令执行的当前目录(PWD)。
18.Entrypoint: 在启动容器时运行的入口点。
19.NetworkDisabled: 是否禁用网络。
20.MacAddress: 容器的 MAC 地址。注意,此字段在 API 版本 v1.44 后已被废弃,建议使用 EndpointSettings.MacAddress 替代。
21.OnBuild:在 Dockerfile 中定义的 ONBUILD 元数据。这个字段用于保存在构建镜像时定义的 ONBUILD 指令,它们将在基础镜像的构建过程中执行。
22.Labels:容器的标签列表。这个字段是一个映射,用于存储容器的元数据信息,如作者、版本、描述等。标签可以用于组织和识别容器,也可以用于进行元数据查询。
23.StopSignal:停止容器时发送的信号。这个字段指定了停止容器时使用的信号,例如 SIGTERM 或 SIGKILL。
24.StopTimeout:停止容器的超时时间(以秒为单位)。这个字段指定了在发送停止信号后等待容器停止的时间。如果容器在超时时间内未停止,则强制终止。
25.Shell:用于 shell 形式的 RUN、CMD、ENTRYPOINT 的 shell。这个字段指定了容器内部使用的 shell 解释器,用于执行 Dockerfile 中的命令。omitempty 表示如果字段为空,则在 JSON 输出中省略该字段。
基本操作demo
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
)
func main() {
// 初始化 Docker 客户端
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
panic(err)
}
//创建容器的配置信息
createConfig := &container.Config{
Image: "your_image_name",
// 可以根据需要配置其他容器参数
}
//停止容器的配置信息
stopConfig := container.StopOptions{}
//删除容器的配置信息
removeOptions := types.ContainerRemoveOptions{
RemoveVolumes: true, // 删除容器关联的卷
Force: true, // 强制删除容器
}
// 列出所有容器的列表
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
if err != nil {
panic(err)
}
//操作每个容器的信息和容器的各种操作
for _, dockerContainer := range containers {
fmt.Printf("容器 ID:%s\n", dockerContainer.ID)
fmt.Printf("容器 名称:%s\n", dockerContainer.Names)
// 在这里可以添加逻辑来判断特定条件下的容器,并对其进行操作
// 例如,暂停、删除等操作
//容器的创建
//使用容器的名字创建容器,配置文件配置镜像等等信息。
//创建容器的时候返回创建的容器ID
createID, err := cli.ContainerCreate(context.Background(), createConfig, nil, nil, nil, "my-container-18")
if err != nil {
panic(err)
}
fmt.Println("创建的容器ID为: ", createID)
//容器的删除
err = cli.ContainerRemove(context.Background(), dockerContainer.ID, removeOptions)
if err != nil {
panic(err)
}
//容器的暂停
err = cli.ContainerPause(context.Background(), dockerContainer.ID)
if err != nil {
panic(err)
}
//容器的恢复
err = cli.ContainerUnpause(context.Background(), dockerContainer.ID)
if err != nil {
panic(err)
}
//容器的停止
err = cli.ContainerStop(context.Background(), dockerContainer.ID, stopConfig)
if err != nil {
panic(err)
}
//容器的重启
err = cli.ContainerRestart(context.Background(), dockerContainer.ID, stopConfig)
if err != nil {
panic(err)
}
}
}
查找容器信息
cmd
对应于cmd的命令如下:
docker ps
类似于cmd的方式,这里可以使用golang程序拿到如下字段信息,查出当前运行的所有容器的信息。
实例
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
)
/*
需求:
尝试在golang中拉取镜像、创建容器、删除容器、停止容器、暂停容器、恢复容器、重启容器。
运行容器、怎么使用docker run去运行一个容器、怎么使用docer build命令
看看其他在docker-cli中执行的命令是否使用go程序也能够正常执行。
*/
func main() {
// 初始化 Docker 客户端
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
panic(err)
}
// 先得到列出所有容器的列表
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
if err != nil {
panic(err)
}
// 对应为docker ps -a 命令
// 再从列表中拿到信息
for _, container := range containers {
fmt.Printf("CONTAINER ID: %s\n", container.ID)
fmt.Printf("IMAGE: %s \n", container.Image)
fmt.Printf("COMMAND: %s \n", container.Command)
fmt.Printf("CREATED: %s \n", container.Created)
fmt.Printf("Status: %s \n", container.Status)
fmt.Printf("PORTS: %s \n", container.Ports)
fmt.Printf("NAMES:%s\n", container.Names)
}
}
运行结果
遍历容器,拿到容器的各种字段信息,与docker ps 命令的信息一致。
创建容器
cmd
运行容器,一般是指定容器内的端口和容器的名字(不能与之前的名字重复)
--expose:编辑容器内的端口
--name:编辑容器的名字
最后的my-golang-app 为镜像源
docker run --expose 3888/tcp --name mycontainer-15 my-golang-app
结果如下:
实例
package main
import (
"context"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"io"
"log"
"os"
)
func main() {
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Fatal(err)
}
//配置容器的各种信息,如镜像源、容器内的端口
containerConfig := &container.Config{
Image: "my-golang-app",
ExposedPorts: nat.PortSet{
"3889/tcp": {},
},
}
hostConfig := &container.HostConfig{}
networkingConfig := &network.NetworkingConfig{}
//创建容器
resp, err := cli.ContainerCreate(ctx, containerConfig, hostConfig, networkingConfig, nil, "mycontainer-20")
if err != nil {
log.Fatal(err)
}
//启动容器
if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
log.Fatal(err)
}
//容器在后台运行
//fmt.Println("容器ID为: " , resp.ID)
// 获取容器的日志
out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true})
if err != nil {
log.Fatal(err)
}
defer out.Close()
// 打印容器的日志到控制台
go func() {
_, err := io.Copy(os.Stdout, out)
if err != nil && err != io.EOF {
log.Fatal(err)
}
}()
// 等待容器运行完成
statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
for {
select {
case err :=
log.Fatal(err)
}
case
// 创建 Docker 客户端
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 定义要删除的容器 ID
containerID := "d815a35c7822"
// 定义删除容器时的选项
options := types.ContainerRemoveOptions{
Force: true, // 强制删除容器
RemoveVolumes: true, // 删除关联的数据卷
RemoveLinks: false, // 不删除关联的链接
}
// 调用 ContainerRemove 方法删除容器
err = cli.ContainerRemove(context.Background(), containerID, options)
if err != nil {
fmt.Printf("Failed to remove container: %v\n", err)
} else {
fmt.Println("Container removed successfully")
}
}
// 创建 Docker 客户端
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 定义要停止的容器 ID
containerID := "b50423e8aade"
stopOptions := container.StopOptions{}
// 调用 ContainerStop 方法停止容器
err = cli.ContainerStop(context.Background(), containerID, stopOptions)
if err != nil {
fmt.Printf("Failed to stop container: %v\n", err)
} else {
fmt.Println("Container stopped successfully")
}
}
// 创建 Docker 客户端
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 定义要重启的容器 ID
containerID := "746a98dfb20c"
topOptions := container.StopOptions{}
// 调用 ContainerRestart 方法重启容器
err = cli.ContainerRestart(context.Background(), containerID, topOptions)
if err != nil {
panic(err)
}
fmt.Printf("Container %s has been restarted.\n", containerID)
}
// 创建 Docker 客户端
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 定义要暂停的容器 ID
containerID := "e4d6650df3af"
// 暂停容器
err = cli.ContainerPause(context.Background(), containerID)
if err != nil {
fmt.Printf("Failed to pause container: %v\n", err)
} else {
fmt.Println("Container paused successfully")
}
}
// 创建 Docker 客户端
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 定义要暂停的容器 ID
containerID := "e4d6650df3af"
// 暂停容器
err = cli.ContainerPause(context.Background(), containerID)
if err != nil {
fmt.Printf("Failed to pause container: %v\n", err)
} else {
fmt.Println("Container paused successfully")
}
}
// 创建 Docker 客户端
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 定义要进入的容器 ID
containerID := "e4d6650df3af"
// 定义进入容器时的选项
options := types.ContainerAttachOptions{
Stream: true,
Stdin: true,
Stdout: true,
Stderr: true,
}
// 调用 ContainerAttach 方法进入容器
resp, err := cli.ContainerAttach(context.Background(), containerID, options)
if err != nil {
panic(err)
}
defer resp.Close()
// 将容器的标准输入输出连接到当前进程的标准输入输出
go io.Copy(os.Stdout, resp.Reader)
go io.Copy(resp.Conn, os.Stdin)
// 等待用户输入以继续运行
fmt.Println("Press enter to exit...")
fmt.Scanln()
}
// 创建 Docker 客户端
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 定义要进入的容器 ID
containerID := "e4d6650df3af"
// 定义要执行的命令
cmd := []string{"sh"} // 这里可以根据需要修改为其他交互式 shell,如 bash
// 准备执行命令的选项
createResp, err := cli.ContainerExecCreate(context.Background(), containerID, types.ExecConfig{
Cmd: cmd,
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
Tty: true,
})
if err != nil {
panic(err)
}
// 连接到正在运行的命令以进行交互
resp, err := cli.ContainerExecAttach(context.Background(), createResp.ID, types.ExecStartCheck{
Tty: true,
})
if err != nil {
panic(err)
}
defer resp.Close()
// 将容器的标准输入输出连接到当前进程的标准输入输出
go func() {
if _, err := io.Copy(os.Stdout, resp.Reader); err != nil {
panic(err)
}
}()
go func() {
if _, err := io.Copy(resp.Conn, os.Stdin); err != nil {
panic(err)
}
}()
// 等待用户输入以继续运行
fmt.Println("Press enter to exit...")
fmt.Scanln()
}
// 创建 Docker 客户端
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 定义要拉取的镜像的名称和标签
imageName := "redis"
imageTag := "latest"
imageRef := imageName + ":" + imageTag
// 拉取镜像
out, err := cli.ImagePull(context.Background(), imageRef, types.ImagePullOptions{})
if err != nil {
panic(err)
}
defer out.Close()
// 解析拉取镜像的输出
var pullResponse struct {
Status string `json:"status"`
}
if err := json.NewDecoder(out).Decode(&pullResponse); err != nil {
panic(err)
}
fmt.Printf("Pulling image %s: %s\n", imageRef, pullResponse.Status)
}
// 创建 Docker 客户端
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 定义要拉取的镜像的名称和标签
imageName := "redis"
imageTag := "latest"
imageRef := imageName + ":" + imageTag
// 拉取镜像
out, err := cli.ImagePull(context.Background(), imageRef, types.ImagePullOptions{})
if err != nil {
panic(err)
}
defer out.Close()
// 解析拉取镜像的输出
var pullResponse struct {
Status string `json:"status"`
}
if err := json.NewDecoder(out).Decode(&pullResponse); err != nil {
panic(err)
}
fmt.Printf("Pulling image %s: %s\n", imageRef, pullResponse.Status)
}
Resources: container.Resources{
Memory: 512000000, // 设置内存限制为 512MB
NanoCPUs: 1000000000, // 设置 CPU 配额(以纳秒为单位)
},
}
"80/tcp": "8080",
}
// 容器挂载卷
volumeMounts := []mount.Mount{
{
Type: mount.TypeBind,
Source: "/host/path", // 宿主机路径
Target: "/container/path", // 容器路径
},
}
// 创建 Docker 客户端
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Fatal(err)
}
// 容器ID,需要根据实际情况修改
containerID := "your_container_id_here"
// 配置更新
updateConfig := container.UpdateConfig{
Resources: container.Resources{
Memory: 512000000, // 设置内存限制为 512MB
NanoCPUs: 1000000000, // 设置 CPU 配额(以纳秒为单位)
},
}
// 执行容器更新
err = updateContainer(cli, containerID, updateConfig)
if err != nil {
log.Fatal(err)
}
fmt.Println("容器配置已更新")
}
// updateContainer 函数用于更新容器的配置信息
func updateContainer(cli *client.Client, containerID string, updateConfig container.UpdateConfig) error {
ctx := context.Background()
// 执行容器更新
_, err := cli.ContainerUpdate(ctx, containerID, updateConfig)
if err != nil {
return err
}
return nil
}
if err := cli.NewVersionError(ctx, "1.30", "config update"); err != nil {
return err
}
query := url.Values{}
query.Set("version", version.String())
resp, err := cli.post(ctx, "/configs/"+id+"/update", query, config, nil)
ensureReaderClosed(resp)
return err
}
Annotations
Data []byte `json:",omitempty"`
// Templating controls whether and how to evaluate the config payload as
// a template. If it is not set, no templating is used.
Templating *Driver `json:",omitempty"`
}
Name string `json:",omitempty"`
Labels map[string]string `json:"Labels"`
}
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Fatal(err)
}
//查找容器信息
getInfoOptions := types.ContainerListOptions{}
getContainerInfo(cli, getInfoOptions)
//配置创建容器的属性
containerConfig := &container.Config{
Image: "my-golang-app",
ExposedPorts: nat.PortSet{
"3889/tcp": {},
},
}
//配置容器主机的属性
//主要用于配置容器的运行环境和资源限制等主机级别的设置
//配置的是容器的主机配置,而不是宿主机(即物理计算机或虚拟机)的主机配置。
hostConfig := &container.HostConfig{}
//主要用于配置容器的网络连接和端口映射等网络设置
networkingConfig := &network.NetworkingConfig{}
//主要用于指定容器的运行平台信息,以便 Docker 在部署时选择合适的环境。
platformConfig := &v1.Platform{}
//创建的容器名字,唯一标识
containerName := "mycontainer-30"
//调用createContainer创建容器并启动
containerId, err := createContainer(cli, containerConfig, hostConfig, networkingConfig, platformConfig, containerName)
fmt.Printf("容器%s已创建好 ", containerId)
// 删除容器是通过Id进行删除的,需要根据名字查找到容器Id
// 根据容器的名字查找出要删除容器的Id
containerID, err := getContainerIDByName(cli, containerName)
if err != nil {
log.Fatal(err)
}
// 定义删除容器时的选项
removeOptions := types.ContainerRemoveOptions{
Force: true, // 强制删除容器
RemoveVolumes: true, // 删除关联的数据卷
RemoveLinks: false, // 不删除关联的链接
}
// 调用removeContainer删除容器
removeContainer(cli, containerID, removeOptions)
//根据容器的新配置重新创建容器
reUpdateContainer(cli, removeOptions, containerConfig, hostConfig, networkingConfig, platformConfig, containerName)
// 停止容器
stopOptions := container.StopOptions{}
stopContainer(cli, containerID, stopOptions)
// 重启容器
restartContainer(cli, containerID, stopOptions)
// 暂停容器
pauseContainer(cli, containerID)
// 恢复暂停
unpauseContainer(cli, containerID)
// 定义进入容器时的选项
attachOptions := types.ContainerAttachOptions{
Stream: true,
Stdin: true,
Stdout: true,
Stderr: true,
}
attachContainer(cli, containerID, attachOptions)
// 定义以命令行进入容器的选项
execAttachConfig := types.ExecConfig{
Cmd: []string{"sh"},
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
Tty: true,
}
execAttachCheck := types.ExecStartCheck{
Tty: true,
}
execAttachContainer(cli, containerID, execAttachConfig, execAttachCheck)
// 定义拉取镜像的选项
// 定义要拉取的镜像的名称和标签
imageName := "redis"
imageTag := "latest"
imageRef := imageName + ":" + imageTag
imagePulloptions := types.ImagePullOptions{}
pullImage(cli, imageRef, imagePulloptions)
//获取容器内所有镜像的信息
getImageOptions := types.ImageListOptions{}
err = getAllImagesInfo(cli, getImageOptions)
if err != nil {
log.Fatal(err)
}
// 定义更新容器的选项
// 更新容器配置信息
// 配置更新
updateConfig := container.UpdateConfig{
Resources: container.Resources{
// Minimum memory limit allowed is 6MB
// 单位为byte(字节数)
Memory: 60000000,
MemorySwap: 60000000, //设置Memory小于交换内存MemorySwap 需要同时配置MemorySwap
NanoCPUs: 1, // 设置 CPU 配额(以纳秒为单位)范围: 0.01 - 8.00
},
}
err = updateContainer(cli, containerID, updateConfig)
if err != nil {
log.Fatal(err)
}
}
/*
作用: 查找出容器的所有信息(容器ID、镜像名、端口、运行状态等等)
*/
func getContainerInfo(cli *client.Client, getInfoOptions types.ContainerListOptions) {
// 先得到列出所有容器的列表
containers, err := cli.ContainerList(context.Background(), getInfoOptions)
if err != nil {
panic(err)
}
// 对应为docker ps -a 命令
// 再从列表(map)中拿到信息
for _, container := range containers {
fmt.Printf("CONTAINER ID: %s\n", container.ID)
fmt.Printf("IMAGE: %s \n", container.Image)
fmt.Printf("COMMAND: %s \n", container.Command)
fmt.Printf("CREATED: %s \n", container.Created)
fmt.Printf("Status: %s \n", container.Status)
fmt.Printf("PORTS: %s \n", container.Ports)
fmt.Printf("NAMES:%s\n", container.Names)
}
}
/*
作用: 根据容器名字和配置的创建选项创建容器
*/
func createContainer(cli *client.Client, containerConfig *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platformConfig *v1.Platform, containerName string) (containerId string, err error) {
// 创建容器
resp, err := cli.ContainerCreate(context.Background(), containerConfig, hostConfig, networkingConfig, platformConfig, containerName)
if err != nil {
log.Fatal(err)
}
// 启动容器
if err := cli.ContainerStart(context.Background(), resp.ID, types.ContainerStartOptions{}); err != nil {
log.Fatal(err)
}
//返回创建好的容器ID
return resp.ID, err
}
/*
作用: 根据容器ID和配置的删除选项删除容器
*/
func removeContainer(cli *client.Client, containerID string, removeOptions types.ContainerRemoveOptions) {
// 调用 ContainerRemove 方法删除容器
err := cli.ContainerRemove(context.Background(), containerID, removeOptions)
if err != nil {
fmt.Printf("Failed to remove container: %v\n", err)
} else {
fmt.Println("Container removed successfully")
}
}
/*
作用: 根据容器ID和配置的停止选项停止容器
*/
func stopContainer(cli *client.Client, containerID string, stopOptions container.StopOptions) {
// 调用 ContainerStop 方法停止容器
err := cli.ContainerStop(context.Background(), containerID, stopOptions)
if err != nil {
fmt.Printf("Failed to stop container: %v\n", err)
} else {
fmt.Println("Container stopped successfully")
}
}
/*
作用: 根据容器ID和配置的停止选项重启容器
*/
func restartContainer(cli *client.Client, containerID string, stopOptions container.StopOptions) {
// 调用 ContainerRestart 方法重启容器
err := cli.ContainerRestart(context.Background(), containerID, stopOptions)
if err != nil {
panic(err)
}
fmt.Printf("Container %s has been restarted.\n", containerID)
}
/*
作用: 根据容器ID暂停容器
*/
func pauseContainer(cli *client.Client, containerID string) {
// 暂停容器
err := cli.ContainerPause(context.Background(), containerID)
if err != nil {
fmt.Printf("Failed to pause container: %v\n", err)
} else {
fmt.Println("Container paused successfully")
}
}
/*
作用: 根据容器ID恢复容器暂停
*/
func unpauseContainer(cli *client.Client, containerID string) {
// 恢复暂停
err := cli.ContainerUnpause(context.Background(), containerID)
if err != nil {
fmt.Printf("Failed to pause container: %v\n", err)
} else {
fmt.Println("Container paused successfully")
}
}
/*
作用: 根据容器ID和配置的进入选项进入容器内部
*/
func attachContainer(cli *client.Client, containerID string, attachOptions types.ContainerAttachOptions) {
// 调用 ContainerAttach 方法进入容器
resp, err := cli.ContainerAttach(context.Background(), containerID, attachOptions)
if err != nil {
panic(err)
}
defer resp.Close()
// 将容器的标准输入输出连接到当前进程的标准输入输出
go io.Copy(os.Stdout, resp.Reader)
go io.Copy(resp.Conn, os.Stdin)
// 等待用户输入以继续运行
fmt.Println("Press enter to exit...")
fmt.Scanln()
}
/*
作用: 通过容器ID配置的进入选项以命令行的方式进入容器内部
*/
func execAttachContainer(cli *client.Client, containerID string, execAttachConfig types.ExecConfig, execAttachCheck types.ExecStartCheck) {
// 准备执行命令的选项
createResp, err := cli.ContainerExecCreate(context.Background(), containerID, execAttachConfig)
if err != nil {
panic(err)
}
// 连接到正在运行的命令以进行交互
resp, err := cli.ContainerExecAttach(context.Background(), createResp.ID, execAttachCheck)
if err != nil {
panic(err)
}
defer resp.Close()
// 将容器的标准输入输出连接到当前进程的标准输入输出
go func() {
if _, err := io.Copy(os.Stdout, resp.Reader); err != nil {
panic(err)
}
}()
go func() {
if _, err := io.Copy(resp.Conn, os.Stdin); err != nil {
panic(err)
}
}()
// 等待用户输入以继续运行
fmt.Println("Press enter to exit...")
fmt.Scanln()
}
/*
作用: 通过配置拉取的镜像名和拉取选项拉取镜像
*/
func pullImage(cli *client.Client, imageRef string, imagePulloptions types.ImagePullOptions) {
// 拉取镜像
out, err := cli.ImagePull(context.Background(), imageRef, imagePulloptions)
if err != nil {
panic(err)
}
defer out.Close()
// 解析拉取镜像的输出
var pullResponse struct {
Status string `json:"status"`
}
if err := json.NewDecoder(out).Decode(&pullResponse); err != nil {
panic(err)
}
fmt.Printf("Pulling image %s: %s\n", imageRef, pullResponse.Status)
}
/*
作用: 通过容器ID和编写的更新配置动态更新容器配置信息(主要是资源限制、重启选项)
*/
func updateContainer(cli *client.Client, containerID string, updateConfig container.UpdateConfig) error {
// 执行容器更新
_, err := cli.ContainerUpdate(context.Background(), containerID, updateConfig)
if err != nil {
return err
}
fmt.Println("容器配置已更新")
return nil
}
/*
作用: 根据容器名字和容器的新配置创建容器,用于对容器的配置进行静态的修改。
*/
func reUpdateContainer(cli *client.Client, removeOptions types.ContainerRemoveOptions, containerConfig *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platformConfig *v1.Platform, containerName string) {
// 一开始调用函数时就要传入创建、删除容器的配置
//传入要删除的名字,得到要删除的容器ID。
containerID, err := getContainerIDByName(cli, containerName)
if err != nil {
log.Fatal(err)
}
//删除容器
removeContainer(cli, containerID, removeOptions)
//调用创建api,创建新的容器
containerId, err := createContainer(cli, containerConfig, hostConfig, networkingConfig, platformConfig, containerName)
fmt.Printf("容器%s已重新创建好 ", containerId)
}
/*
作用:通过容器名查找容器ID,常用于需要使用容器ID的容器操作
*/
func getContainerIDByName(cli *client.Client, containerName string) (string, error) {
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
if err != nil {
return "", err
}
for _, container := range containers {
for _, name := range container.Names {
// 注意: 容器名字以 "/" 开头,例如:你创建的名字为mycontainer-30 实际在容器中为"/mycontainer-30"
// 在查找时前面要拼接上一个 /
if name == "/"+containerName {
return container.ID, nil
}
}
}
return "", fmt.Errorf("未找到容器名称为 %s 的容器", containerName)
}
/*
作用: 获取容器的所有镜像信息(不包含镜像的名字)
*/
func getAllImagesInfo(cli *client.Client, getImageOptions types.ImageListOptions) error {
// 调用 Docker API 获取所有镜像的摘要信息
images, err := cli.ImageList(context.Background(), getImageOptions)
if err != nil {
return err
}
// 打印每个镜像的信息
for _, image := range images {
fmt.Printf("镜像ID: %s\n", image.ID)
fmt.Printf("标签: %s\n", image.Labels["com.docker.compose.version"])
fmt.Printf("大小: %d bytes\n", image.Size)
fmt.Println("--------------")
}
return nil
}



