1. 准备
1.1 docker开放远程API端口
- 修改
/etc/systemd/system/docker.service
文件
注释原来的ExecStart,添加一行新的如下:
| |
| ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock |
说明:
- 第一个
-H tcp://0.0.0.0:2375
是远程调用 - 第二个
-H unix:///var/run/docker.sock
是本地调用(如果不写本地将不能调用)
| [root@liubei-test ~]# systemctl daemon-reload |
| [root@liubei-test ~]# systemctl restart docker.service |
| [root@liubei-test ~]# netstat -ntlp |
| Active Internet connections (only servers) |
| Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name |
| …… |
| tcp6 0 0 :::2375 :::* LISTEN 5632/dockerd |
| …… |
| >2379这个端口是docker的api端口 |
1.2 防火墙策略
- docker API需要对应的安全策略
- tls策略,如果控制大量虚拟机,没有内部DNS的情况似乎并不好用
因此建议此时使用防火墙策略:
| iptables -P INPUT ACCEPT |
| iptables -I INPUT -p tcp --dport 2375 -j DROP |
| iptables -I INPUT -p tcp --dport 2375 -s 10.10.87.18 -j ACCEPT |
2. 链接docker
2.1 语法
| func NewClientWithOpts(ops ...Opt) (*Client, error) |
| cli, err = client.NewClientWithOpts(client.WithAPIVersionNegotiation(), client.WithHost("tcp://10.10.239.32:2375")) |
client.WithAPIVersionNegotiation()
如是——协商API版本,如果不添加,可能会报错,比如:
| 2023/03/14 13:55:53 Error response from daemon: client version 1.42 is too new. Maximum supported API version is 1.40 |
2.2 常用 ops
| client.WithAPIVersionNegotiation() |
| client.WithTimeout(10*time.Second) |
如果后边查看实时日志用这个会自动断开
2.3 完整示例
| package main |
| |
| import ( |
| "context" |
| "fmt" |
| "github.com/docker/docker/api/types" |
| "github.com/docker/docker/client" |
| "log" |
| ) |
| |
| |
| func main() { |
| cli, err := ConnectDocker() |
| if err != nil { |
| fmt.Println(err) |
| } else { |
| fmt.Println("docker API 链接成功") |
| } |
| } |
| |
| 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 |
| } |
| |
3. 镜像操作
3.1 获取镜像列表
| func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]ImageSummary, error) |
| ctx := context.Background() |
| images, err := cli.ImageList(ctx, types.ImageListOptions{All: true}) |
| |
| import ( |
| "bufio" |
| "context" |
| "fmt" |
| "github.com/docker/docker/api/types" |
| "github.com/docker/docker/client" |
| "io" |
| "log" |
| "os" |
| ) |
| |
| func main() { |
| cli, err := ConnectDocker() |
| defer cli.Close() |
| if err != nil { |
| fmt.Println(err) |
| } else { |
| fmt.Println("docker 链接成功") |
| } |
| |
| err = GetImageList(cli) |
| if err != nil { |
| fmt.Println(err) |
| } |
| } |
| |
| |
| |
| 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 GetImageList(cli *client.Client) error { |
| ctx := context.Background() |
| images, err := cli.ImageList(ctx, types.ImageListOptions{All: true}) |
| if err != nil { |
| return err |
| } |
| |
| for _, image := range images { |
| fmt.Printf("================\n%q %q\n", image.RepoTags, image.ID) |
| } |
| return nil |
| } |
| |
| docker 链接成功 |
| ================ |
| ["harbocto.xxx.com.cn/crow/crow-qin:latest"] "sha256:04f135a90290c42b8cf9b52395c04753b4d9ed48ddae7c714a0eccdf8acd9682" |
| ================ |
| [] "sha256:b8f6736f7d1cee3e993bf0ba2a308fb747ed25dbd98fa2a2aba23b726cd8311b" |
| ================ |
| …… |
3.2 获取指定镜像信息
| func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (ImageInspect, []byte, error) |
| imageInfo,imageInfoByte, err = cli.ImageInspectWithRaw(ctx, imageID) |
| 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 链接成功") |
| } |
| imageId := "04f135a90290" |
| imageInfo, err := GetImage(cli, imageId) |
| if err != nil { |
| fmt.Println(err) |
| return |
| } |
| |
| fmt.Printf("查询到镜像 %q", imageInfo.RepoTags) |
| } |
| |
| func GetImage(cli *client.Client, imageID string) (imageInfo types.ImageInspect, err error) { |
| ctx := context.Background() |
| imageInfo, _, err = cli.ImageInspectWithRaw(ctx, imageID) |
| if err != nil { |
| return imageInfo, err |
| } |
| return imageInfo, nil |
| } |
| docker 链接成功 |
| 查询到镜像 ["harbocto.xxx.com.cn/crow-test/crow-qin:latest" "harbocto.xxx.com.cn/crow/crow-qin:latest"] |
结果可见,改id的镜像有两个RepoTag
3.3 镜像拉取
| func (cli *Client) ImagePull(ctx context.Context, refStr string, options ImagePullOptions) (io.ReadCloser, error) |
| ctx := context.Background() |
| reader, err := Cli.ImagePull(ctx, imageName, types.ImagePullOptions{}) |
| package main |
| |
| import ( |
| "context" |
| "fmt" |
| "github.com/docker/docker/api/types" |
| "github.com/docker/docker/client" |
| "io" |
| "os" |
| ) |
| |
| var Cli *client.Client |
| |
| func main() { |
| cli, err := ConnectDocker() |
| if err != nil { |
| fmt.Println(err) |
| } else { |
| fmt.Println("docker 链接成功") |
| } |
| |
| err = PullImage(cli, "harbocto.xxx.com.cn/public/redis:6.2.6") |
| if err != nil { |
| fmt.Println(err) |
| } |
| } |
| |
| |
| |
| 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 PullImage(cli *client.Client, imageName string) error { |
| ctx := context.Background() |
| |
| reader, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{}) |
| if err != nil { |
| fmt.Println(err) |
| } |
| |
| _, err = io.Copy(os.Stdout, reader) |
| if err != nil { |
| return err |
| } |
| |
| return nil |
| } |
输出
| docker 链接成功 |
| {"status":"Pulling from public/redis","id":"6.2.6"} |
| {"status":"Pulling fs layer","progressDetail":{},"id":"a2abf6c4d29d"} |
| {"status":"Pulling fs layer","progressDetail":{},"id":"c7a4e4382001"} |
| …… |
| {"status":"Extracting","progressDetail":{"current":409,"total":409},"progress":"[==================================================\u003e] 409B/409B","id":"1abfd3011519"} |
| {"status":"Pull complete","progressDetail":{},"id":"1abfd3011519"} |
| {"status":"Digest: sha256:563888f63149e3959860264a1202ef9a644f44ed6c24d5c7392f9e2262bd3553"} |
| {"status":"Status: Downloaded newer image for harbocto.boe.com.cn/public/redis:6.2.6"} |
| 镜像拉取成功 |
3.4 拉取私有仓库镜像
- 语法
同镜像拉取,添加RegistryAuth
参数 - 语法示例
| out, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{RegistryAuth: authStr}) |
| package main |
| |
| import ( |
| "context" |
| "encoding/base64" |
| "encoding/json" |
| "fmt" |
| "github.com/docker/docker/api/types" |
| "github.com/docker/docker/client" |
| "io" |
| "os" |
| ) |
| |
| func main() { |
| cli, err := ConnectDocker() |
| if err != nil { |
| fmt.Println(err) |
| } else { |
| fmt.Println("docker 链接成功") |
| } |
| |
| err = PullPrivateImage(cli, "harbocto.boe.com.cn/crow-test/crow-qin") |
| if err != nil { |
| fmt.Println(err) |
| } |
| |
| } |
| |
| |
| |
| func PullPrivateImage(cli *client.Client, imageName string) error { |
| ctx := context.Background() |
| authConf := types.AuthConfig{ |
| Username: "10264953", |
| Password: "30gmcyt8Kllyhy", |
| } |
| encodeJson, _ := json.Marshal(authConf) |
| authStr := base64.StdEncoding.EncodeToString(encodeJson) |
| out, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{RegistryAuth: authStr}) |
| if err != nil { |
| fmt.Println(err) |
| return err |
| } |
| defer out.Close() |
| _, err = io.Copy(os.Stdout, out) |
| if err != nil { |
| return err |
| } |
| |
| return nil |
| } |
3.5 修改 REPOSITORY:TAG
| func (cli *Client) ImageTag(ctx context.Context, source string, target string) error |
| ctx := context.Background() |
| err := cli.ImageTag(ctx, "harbocto.boe.com.cn/crow/crow-qin", "harbocto.boe.com.cn/public/crow-qin:0323") |
| package main |
| |
| import ( |
| "context" |
| "fmt" |
| "github.com/docker/docker/client" |
| ) |
| |
| func main() { |
| cli, err := ConnectDocker() |
| if err != nil { |
| fmt.Println(err) |
| } else { |
| fmt.Println("docker 链接成功") |
| } |
| |
| err = AddNewTag(cli, "harbocto.boe.com.cn/crow/crow-qin", "harbocto.boe.com.cn/public/crow-qin:0323") |
| if err != nil { |
| fmt.Println(err) |
| return |
| } |
| fmt.Println("REPOSITORY:TAG 添加成功") |
| } |
| |
| func AddNewTag(cli *client.Client, sourceImageName string, newImageName string) error { |
| ctx := context.Background() |
| err := cli.ImageTag(ctx, sourceImageName, newImageName) |
| if err != nil { |
| return err |
| } |
| return nil |
| } |
| docker 链接成功 |
| REPOSITORY:TAG 添加成功 |
3.6 删除镜像
| func (cli *Client) ImageRemove(ctx context.Context, imageID string, options ImageRemoveOptions) ([]ImageDeleteResponseItem, error) |
| ctx := context.Background() |
| imageDeleteResponseItems, err = cli.ImageRemove(ctx, imageId, types.ImageRemoveOptions{Force: true}) |
| 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 链接成功") |
| } |
| |
| imageDeleteResponseItems, err := DeleteImage(cli, "04f135a90290") |
| if err != nil { |
| fmt.Println(err) |
| return |
| } |
| fmt.Println("==== 被删除的 REPOSITORY:TAG ====\n", imageDeleteResponseItems) |
| } |
| |
| func DeleteImage(cli *client.Client, imageId string) (imageDeleteResponseItems []types.ImageDeleteResponseItem, err error) { |
| ctx := context.Background() |
| imageDeleteResponseItems, err = cli.ImageRemove(ctx, imageId, types.ImageRemoveOptions{Force: true}) |
| if err != nil { |
| fmt.Println(err) |
| return imageDeleteResponseItems, err |
| } |
| return imageDeleteResponseItems, nil |
| } |
输出
| docker 链接成功 |
| ==== 被删除的 REPOSITORY:TAG ==== |
| [{ harbocto.boe.com.cn/crow-test/crow-qin:latest} { harbocto.boe.com.cn/crow-test/crow-qin@sha256:5891ae5e691914196af46e869a6cba45c6e53266b4110b85c5c37385cc3b6b84} { harbocto.boe.com.cn/crow/crow-qin:latest} { harbocto.boe |
| .com.cn/crow/crow-qin@sha256:5891ae5e691914196af46e869a6cba45c6e53266b4110b85c5c37385cc3b6b84} { harbocto.boe.com.cn/public/crow-qin:0323} { harbocto.boe.com.cn/public/crow-qin:latest} {sha256:04f135a90290c42b8cf9b52395c047 |
| 53b4d9ed48ddae7c714a0eccdf8acd9682 } {sha256:b823e639a7311f26a530dad46f8ac237412fb28455213bd10f1167920e3afcd4 } {sha256:28b4ee770c69121697cce33f6c52990920c3023b4cc2cf14711e2e489ea5259f } {sha256:42197fd514211b6e3d9f10f9afcd |
| 4ad95620371f22f16656fd671e446c3e3a1e } {sha256:89ae5c4ee501a09c879f5b58474003539ab3bb978a553af2a4a6a7de248b5740 }] |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了