使用Golang玩转Docker API的实践

Docker 提供了一个与 Docker 守护进程交互的 API (称为Docker Engine API),我们可以使用官方提供的 Go 语言的 SDK 进行构建和扩展 Docker 应用程序和解决方案。

安装 SDK

通过下面的命令就可以安装 SDK 了:

go get github.com/docker/docker/client

管理本地的 Docker

该部分会介绍如何使用 Golang + Docker API 进行管理本地的 Docker。

运行容器

第一个例子将展示如何运行容器,相当于 docker run docker.io/library/alpine echo "hello world":

package main

import (
 "context"
 "io"
 "os"

 "github.com/docker/docker/api/types"
 "github.com/docker/docker/api/types/container"
 "github.com/docker/docker/client"
 "github.com/docker/docker/pkg/stdcopy"
)

func main() {
 ctx := context.Background()
 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 if err != nil {
 panic(err)
 }

 reader, err := cli.ImagePull(ctx, "docker.io/library/alpine", types.ImagePullOptions{})
 if err != nil {
 panic(err)
 }
 io.Copy(os.Stdout, reader)

 resp, err := cli.ContainerCreate(ctx, &container.Config{
 Image: "alpine",
 Cmd: []string{"echo", "hello world"},
 }, nil, nil, "")
 if err != nil {
 panic(err)
 }

 if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
 panic(err)
 }

 statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
 select {
 case err := <-errCh:
 if err != nil {
  panic(err)
 }
 case <-statusCh:
 }

 out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true})
 if err != nil {
 panic(err)
 }

 stdcopy.StdCopy(os.Stdout, os.Stderr, out)
}

后台运行容器

还可以在后台运行容器,相当于 docker run -d bfirsh/reticulate-splines:

package main

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

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

func main() {
 ctx := context.Background()
 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 if err != nil {
 panic(err)
 }

 imageName := "bfirsh/reticulate-splines"

 out, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{})
 if err != nil {
 panic(err)
 }
 io.Copy(os.Stdout, out)

 resp, err := cli.ContainerCreate(ctx, &container.Config{
 Image: imageName,
 }, nil, nil, "")
 if err != nil {
 panic(err)
 }

 if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
 panic(err)
 }

 fmt.Println(resp.ID)
}

查看容器列表

列出正在运行的容器,就像使用 docker ps 一样:

package main

import (
 "context"
 "fmt"

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

func main() {
 ctx := context.Background()
 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 if err != nil {
  panic(err)
 }

 containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
 if err != nil {
  panic(err)
 }

 for _, container := range containers {
  fmt.Println(container.ID)
 }
}

如果是 docker ps -a,我们可以通过修改 types.ContainerListOptions 中的 All 属性达到这个目的:

// type ContainerListOptions struct {
// Quiet bool
// Size bool
// All  bool
// Latest bool
// Since string
// Before string
// Limit int
// Filters filters.Args
// }

options := types.ContainerListOptions{
 All: true,
}
containers, err := cli.ContainerList(ctx, options)
if err != nil {
 panic(err)
}

停止所有运行中的容器

通过上面的例子,我们可以获取容器的列表,所以在这个案例中,我们可以去停止所有正在运行的容器。

注意:不要在生产服务器上运行下面的代码。

package main

import (
 "context"
 "fmt"

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

func main() {
 ctx := context.Background()
 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 if err != nil {
  panic(err)
 }

 containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
 if err != nil {
  panic(err)
 }

 for _, container := range containers {
  fmt.Print("Stopping container ", container.ID[:10], "... ")
  if err := cli.ContainerStop(ctx, container.ID, nil); err != nil {
   panic(err)
  }
  fmt.Println("Success")
 }
}

获取指定容器的日志

通过指定容器的 ID,我们可以获取对应 ID 的容器的日志:

package main

import (
 "context"
 "io"
 "os"

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

func main() {
 ctx := context.Background()
 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 if err != nil {
  panic(err)
 }

 options := types.ContainerLogsOptions{ShowStdout: true}

 out, err := cli.ContainerLogs(ctx, "f1064a8a4c82", options)
 if err != nil {
  panic(err)
 }

 io.Copy(os.Stdout, out)
}

查看镜像列表

获取本地所有的镜像,相当于 docker image ls 或 docker images:

package main

import (
 "context"
 "fmt"

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

func main() {
 ctx := context.Background()
 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 if err != nil {
  panic(err)
 }

 images, err := cli.ImageList(ctx, types.ImageListOptions{})
 if err != nil {
  panic(err)
 }

 for _, image := range images {
  fmt.Println(image.ID)
 }
}

拉取镜像

拉取指定镜像,相当于 docker pull alpine:

package main

import (
 "context"
 "io"
 "os"

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

func main() {
 ctx := context.Background()
 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 if err != nil {
  panic(err)
 }

 out, err := cli.ImagePull(ctx, "alpine", types.ImagePullOptions{})
 if err != nil {
  panic(err)
 }

 defer out.Close()

 io.Copy(os.Stdout, out)
}

拉取私有镜像

除了公开的镜像,我们平时还会用到一些私有镜像,可以是 DockerHub 上私有镜像,也可以是自托管的镜像仓库,比如 harbor。这个时候,我们需要提供对应的凭证才可以拉取镜像。

值得注意的是:在使用 Docker API 的 Go SDK 时,凭证是以明文的方式进行传输的,所以如果是自建的镜像仓库,请务必使用 HTTPS!

package main

import (
 "context"
 "encoding/base64"
 "encoding/json"
 "io"
 "os"

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

func main() {
 ctx := context.Background()
 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 if err != nil {
  panic(err)
 }

 authConfig := types.AuthConfig{
  Username: "username",
  Password: "password",
 }
 encodedJSON, err := json.Marshal(authConfig)
 if err != nil {
  panic(err)
 }
 authStr := base64.URLEncoding.EncodeToString(encodedJSON)

 out, err := cli.ImagePull(ctx, "alpine", types.ImagePullOptions{RegistryAuth: authStr})
 if err != nil {
  panic(err)
 }

 defer out.Close()
 io.Copy(os.Stdout, out)
}

保存容器成镜像

我们可以将一个已有的容器通过 commit 保存成一个镜像:

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() {
 ctx := context.Background()
 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 if err != nil {
  panic(err)
 }

 createResp, err := cli.ContainerCreate(ctx, &container.Config{
  Image: "alpine",
  Cmd: []string{"touch", "/helloworld"},
 }, nil, nil, "")
 if err != nil {
  panic(err)
 }

 if err := cli.ContainerStart(ctx, createResp.ID, types.ContainerStartOptions{}); err != nil {
  panic(err)
 }

 statusCh, errCh := cli.ContainerWait(ctx, createResp.ID, container.WaitConditionNotRunning)
 select {
 case err := <-errCh:
  if err != nil {
   panic(err)
  }
 case <-statusCh:
 }

 commitResp, err := cli.ContainerCommit(ctx, createResp.ID, types.ContainerCommitOptions{Reference: "helloworld"})
 if err != nil {
  panic(err)
 }

 fmt.Println(commitResp.ID)
}

管理远程的 Docker

当然,除了可以管理本地的 Docker, 我们同样也可以通过使用 Golang + Docker API 管理远程的 Docker。

远程连接

默认 Docker 是通过非网络的 Unix 套接字运行的,只能够进行本地通信(/var/run/docker.sock),是不能够直接远程连接 Docker 的。
我们需要编辑配置文件 /etc/docker/daemon.json,并修改以下内容(把 192.168.59.3 改成你自己的 IP 地址),然后重启 Docker:

# vi /etc/docker/daemon.json
{
 "hosts": [
 "tcp://192.168.59.3:2375",
 "unix:///var/run/docker.sock"
 ]
}

systemctl restart docker

修改 client

创建 client 的时候需要指定远程 Docker 的地址,这样就可以像管理本地 Docker 一样管理远程的 Docker 了:

cli, err = client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation(),
 client.WithHost("tcp://192.168.59.3:2375"))

总结

现在已经有很多可以管理 Docker 的产品,它们便是这样进行实现的,比如:portainer

到此这篇关于使用Golang玩转Docker API的实践的文章就介绍到这了,更多相关Golang运行Docker API内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Golang学习笔记之安装Go1.15版本(win/linux/macos/docker安装)

    安装Go1.15版本 大纲 Windows安装GoLinux安装GoMacOS安装GoDocker安装Go总结 视频地址:https://www.bilibili.com/video/BV14a4y177XG?p=3 Windows安装Go 1.点击下载go1.15版本的msi安装包 64位系统 https://studygolang.com/dl/golang/go1.15.windows-amd64.msi 32位系统 https://studygolang.com/dl/golang/go

  • 详解如何在 Docker 中设置 Go 并部署应用

    嗨,在本教程中,我们将学习如何使用 docker 部署 golang web 应用程序. 你可能已经知道,由于 golang 的高性能和可靠性,docker 是完全是用 golang 写的.在我们详细介绍之前,请确保你已经安装了 docker 以及 golang 并对它们有基本了解. 关于 docker Docker 是一个开源程序,它可以将应用及其完整的依赖包捆绑到一起,并打包为容器,与宿主机共享相同的 Linux 内核.另一方面,像 VMware 这样的基于 hypervisor 的虚拟化操

  • docker django无法访问redis容器的解决方法

    docker-compose.yal文件中: redis: image: redis container_name: xdemo.redis ports: - 6379:6379 restart: always django setting.py中配置redis: CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379', "OPTIONS&qu

  • Docker部署Django应用的示例

    之前部署Web应用,没用docker,直接在服务器上部署,使用了fabric+nginx+supervisor+gunicorn部署,可查看我写过的一片博客:部署Web应用.但后来了解了docker,为其"Build,Ship and Run Any App,Anywhere"的思想所折服,觉得这个太牛逼了,所以我也尝试一下自己用docker部署Web应用.本篇文章为了记录我用docker部署web应用的过程和心得. 一.网络架构 我用Visio大概画了一下我的网络架构图: 我构建的容

  • docker中部署golang项目的步骤详解

    理解Docker Docker可以帮您为自己的应用程序创建一个单一的可部署"单位".这样的单位也叫做容器,其中包含了应用程序需要的一切.例如代码(或二进制文件).运行时.系统工具,以及系统库文件.将所有这些需要的内容打包为一个单一的单位,可确保无论将应用程序部署在何处,都能提供完全相同的环境.这种技术还可以帮您维持完全一致的开发和生产环境,通常这些环境是很难被追踪的. 一旦搭建完成,容器的创建和部署将可自动进行.这本身就可以避免一系列问题.这些问题中大部分都是因为文件不同步,或开发和生

  • docker 容器上编译 go 程序提示找不到文件问题

    dockerfile [root@SZB-L0010091 zxg]# cat Dockerfile FROM scratch COPY webdemo / EXPOSE 9999 CMD ["/webdemo"] docker run 报错信息: [root@zxg]# docker run --rm -it -p 9999:9999 web:1.0 panic: standard_init_linux.go:178: exec user process caused "n

  • Docker 部署Django项目的方法示例

    使用docker部署django项目也很简单,挺不错,分享下 环境 默认你已安装好docker环境 django项目大概结构 (p3s) [root@opsweb]# tree opsweb opsweb ├── apps ├── logs ├── manage.py ├── media ├── opsweb ├── README.md ├── requirements.txt └── static 编写Dockerfile 这里指定 Python 版本为docker官方提供的 "0.0.0.0

  • Docker与Golang的巧妙结合

    Docker与Golang的巧妙结合 [编者的话]这是一个展示在使用Go语言时如何让Docker更有用的提示与技巧的简辑.例如,如何使用不同版本的Go工具链来编译Go代码,如何交叉编译到不同的平台(并且测试结果!),或者如何制作真正小的容器镜像. 下面的文章假定你已经安装了Docker.不必是最新版本(这篇文章不会使用Docker任何花哨的功能). 没有go的Go ...意思是:"不用安装go就能使用Go" 如果你写Go代码,或者你对Go语言有一点点兴趣,你肯定要安装了Go编译器和Go

  • 使用Golang玩转Docker API的实践

    Docker 提供了一个与 Docker 守护进程交互的 API (称为Docker Engine API),我们可以使用官方提供的 Go 语言的 SDK 进行构建和扩展 Docker 应用程序和解决方案. 安装 SDK 通过下面的命令就可以安装 SDK 了: go get github.com/docker/docker/client 管理本地的 Docker 该部分会介绍如何使用 Golang + Docker API 进行管理本地的 Docker. 运行容器 第一个例子将展示如何运行容器,

  • golang实现对docker容器心跳监控功能

    自己写的go程序放到线上本来编译成二进制扔上去就行啦,但是怀着一颗docker的心,最终还是将它放到docker容器中运行起来了,运行起来也ok,一个最小容器64M,统一管理起来也方便,但是毕竟是个线上长驻内存的服务程序,万一跑挂了怎么办,如何才能监控它,直接上go代码,网上代码,略微做了下注释,但实测过,真实有效: package main import ( "encoding/json" "errors" "flag" "fmt&q

  • 构建Golang应用最小Docker镜像的实现

    我通常使用docker运行我的 golang 程序,在这里分享一下我构建 docker 镜像的经验.我构建 docker 镜像不仅优化构建后的体积,还要优化构建速度. 示例应用 首先贴出代码例子,我们假设要构建一个 http 服务 package main import ( "fmt" "net/http" "time" "github.com/gin-gonic/gin" ) func main() { fmt.Printl

  • 简单学习Java API 设计实践

    前言 了解在设计 Java API 时应该运用的一些 API 设计实践.这些实践通常很有用,而且可确保 API 能在诸如 OSGi 和 Java Platform Module System (JPMS) 之类的模块化环境中得到正确使用.有些实践是规定性的,有些则是禁止性的.当然,其他良好的 API 设计实践也同样适用. OSGi 环境提供了一个模块化运行时,使用 Java 类加载器概念来强制实施类型可见性封装.每个模块都将有自己的类加载器,该加载器将连接到其他模块的类加载器,以共享导出的包并使

  • 详解docker API管理接口增加CA安全认证

    目录 一.模拟创建CA证书(中间边框的部分) 二.签发服务器端证书(右边蓝色背景部分) 三.签发客户端证书(左边黄色背景的部分) 四.签发证书收尾工作 五.配置docker服务端 六.IDEA配置使用客户端证书 前文中我们曾经介绍过<使用IDEA远程工具>连接Docker REST API,我们会发现一个问题,任何知道Docker 服务器IP.端口的第三方都可以访问这个API,非常的不安全.为了保证Docker API的安全性,我们有必要使用数字证书进行安全验证. 为docker服务端配置服务

  • python调用新浪微博API项目实践

    因为最近接触到调用新浪微博开放接口的项目,所以就想试试用python调用微博API. SDK下载地址:http://open.weibo.com/wiki/SDK 代码不多十几K,完全可以看懂. 有微博账号可以新建一个APP,然后就可以得到app key和app secret,这个是APP获得OAuth2.0授权所必须的. 了解OAuth2可以查看链接新浪微博的说明. OAuth2授权参数除了需要app key和app secret还需要网站回调地址redirect_uri,并且这个回调地址不允

  • Python开发加薪利器之Docker的使用实践

    1. Docker概述 Docker为什么火,因为十分的轻巧. Docker是基于Go语言开发的. 1.1 虚拟机技术VS容器化技术 虚拟机技术: 资源占用 多冗余步骤多 启动慢 容器化技术:容器化技术不是模拟一个完整的操作系统. 1.2 名词概念 镜像(image) docker镜像好比是一个模版,可以通过这个模版来创建容器服务,mysql镜像==>run==>mysql01容器(提供服务),通过这个镜像可以创建多个容器. 容器(container) docker利用容器技术,独立运行一个或

  • 使用Portainer部署Docker容器的项目实践

    一.背景 最近在使用rancher2.5.5部署Redis主从复制的时候,发现rancher会产生很多iptables的规则,这些规则导致我们在部署了rancher的机器上无法使用Redis的主从复制功能,因为我对rancher和k8s的了解也仅限于了解网络架构和使用,对底层并不深入,短期内无法解决这个网络冲突的问题: 因此我将rancher管理docker的模式换成使用protainer的方式,这个portainer相对来说更加轻量级,在搭建过程中也使用了几个小时学习,现在讲整个过程尽量复原给

  • Node.js服务Docker容器化应用实践小结

    本篇不会讲解 Docker 命令的使用.安装等,因为在之前一篇文章一文零基础教你学会 Docker 入门到实践中也已经讲解的很详细了,不清楚的可以点击链接回头在重新看下,本篇重点是介绍 Node.js 项目如何进行 Docker 容器化及一些实践优化,还有一些常见的问题,当然如果还有其它使用上的问题也欢迎大家在评论区进行留言补充. 作者简介:五月君,Nodejs Developer,热爱技术.喜欢分享的 90 后青年,公众号「Nodejs技术栈」,Github 开源项目 www.nodejs.r

随机推荐