文档章节

Docker Remote API如何在开发中使用

clearraining
 clearraining
发布于 2015/01/22 18:47
字数 2196
阅读 113
收藏 2
点赞 0
评论 1

初学docker,了解docker remote API的时候根本不知道怎么使用在开发中,通过DockerClient这个项目能很好的认识到API在开发过程中的使用,如何建立连接等。也希望像我一样的初学者能通过这个项目了解docker API的使用。

一.   基本配置

访问docker远程API有两种方法,使用Unix套接字和HTTP端口。

Unix套接字:docker监听unix:///var/run/docker.sock这个unix套接字。

HTTP远程访问:需要修改配置使能支持远程访问,在ubuntu环境下找到/etc/init/docker.conf文件,找到 DOCKER_OPTS并修改,接着重启docker后台进程。

DOCKER_OPTS="-H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock"
$sudo service docker restart
验证
$netstat -ant  |grep 4243
tcp6       0      0 :::4243                 :::*                    LISTEN

然后就可以访问了。

举例如下:

$curl http://127.0.0.1:4243/info
{"Containers":4,"Debug":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Dirs","63"]],"ExecutionDriver":"native-0.2","IPv4Forwarding":1,"Images":55,"IndexServerAddress":"https://index.docker.io/v1/","InitPath":"/usr/bin/docker","InitSha1":"","KernelVersion":"3.13.0-32-generic","MemoryLimit":1,"NEventsListener":0,"NFd":16,"NGoroutines":15,"OperatingSystem":"Ubuntu precise (12.04.5 LTS)","SwapLimit":0}

$curl GET http://127.0.0.1:4243/containers/json
[{"Command":"crate -Des.cluster.name=cratecluster -Des.node.name=crate1 -Des.transport.publish_port=4300 -Des.network.publish_host=115.159.76.38 -Des.multicast.enabled=false -Des.discovery.zen.ping.unicast.hosts=115.159.76.38:4300,115.159.26.242:4300 -Des.discovery.zen.minimum_master_nodes=2","Created":1418829276,"Id":"dfd58a62a7c941218088f6e43d8dc17ecfb8cd0783e6c4e338c321d6d39c4bbd","Image":"docker.cn/docker/crate:0.45","Names":["/node1"],"Ports":[{"IP":"0.0.0.0","PrivatePort":4200,"PublicPort":4200,"Type":"tcp"},{"IP":"0.0.0.0","PrivatePort":4300,"PublicPort":4300,"Type":"tcp"}],"Status":"Up 2 weeks"}]


如果想要了解完整的docker API可以访问官网:https://docs.docker.com/reference/api/docker_remote_api/ 。

二.  DockerClient  

下面开始进入dockerClient这个项目,dockerclient.go中实现了对docker remote API的封装。

dockerClient项目:https://github.com/samalba/dockerclient

1.创建DockerClient

a. NewDockerClient()

func NewDockerClient(daemonUrl string, tlsConfig *tls.Config) (*DockerClient, error) {
	return NewDockerClientTimeout(daemonUrl, tlsConfig, time.Duration(defaultTimeout))
}

使用NewDockerClient方法新建一个dockerclient,需要传入daemonUrl和tlsConfig两个参数,创建成功会返回一个DockerClient。其中两个参数具体含义如下:

daemonUrl: 需要传入一个后台docker进程的Url,比如unix:///var/run/docker.sock。

tlsConfig: tlsConfig是cropto/tls包中的Config结构类型,Config结构类型用于配置TLS客户端或服务端,具体参阅cropto/tls包。

TLS:Transport Layer Security(安全传输层协议)

TLS用于在两个通信应用程序之间提供保密性和数据完整性。

使用举例:

docker, _ := dockerclient.NewDockerClient("unix:///var/run/docker.sock", nil)

在NewDockerClient方法中调用NewDockerClientTimeout方法实现具体的DockerClient的创建。


b.NewDockerClientTimeout()

func NewDockerClientTimeout(daemonUrl string, tlsConfig *tls.Config, timeout time.Duration) (*DockerClient, error) {
	u, err := url.Parse(daemonUrl)
	if err != nil {
		return nil, err
	}
	if u.Scheme == "tcp" {
		if tlsConfig == nil {
			u.Scheme = "http"
		} else {
			u.Scheme = "https"
		}
	}
	httpClient := newHTTPClient(u, tlsConfig, timeout)
	return &DockerClient{u, httpClient, tlsConfig, 0}, nil
}

需要向NewDockerClientTimeout方法传入三个参数,分别是daemonUrl、tlsConfig和timeout。在此方法中会先解析daemonUrl,net/url包中的Parse方法解析daemonUrl,返回一个URL结构类型。

URL结构类型:

type URL struct {    
    Scheme   string
    Opaque   string    // 编码后的不透明数据
    User     *Userinfo // 用户名和密码信息
    Host     string    // host或host:port
    Path     string
    RawQuery string    // 编码后的查询字符串,没有'?'
    Fragment string    // 引用的片段(文档位置),没有'#'}

URL基本格式如下:

scheme://[userinfo@]host/path[?query][#fragment]

timeout:timeout是time包中的Duration类型,代表两个时间点之间经过的时间,以纳秒为单位。timeout默认为30s(defaultTimeout)

解析完daemonUrl后,对返回的URL的scheme进行判断,tcp协议并且有安全传输协议的设置scheme为https,否则设为http。当然scheme也有可能是unix。接着需要新建一个HTTPClient,通过向newHTTPClient方法传入三个参数,包括解析后的URL、tlsConfig和timeout。


c. newHTTPClient()

func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration) *http.Client {
	httpTransport := &http.Transport{
		TLSClientConfig: tlsConfig,
	}
	switch u.Scheme {
	default:
		httpTransport.Dial = func(proto, addr string) (net.Conn, error) {
			return net.DialTimeout(proto, addr, timeout)
		}
	case "unix":
		socketPath := u.Path
		unixDial := func(proto, addr string) (net.Conn, error) {
			return net.DialTimeout("unix", socketPath, timeout)
		}
		httpTransport.Dial = unixDial
		// Override the main URL object so the HTTP lib won't complain
		u.Scheme = "http"
		u.Host = "unix.sock"
		u.Path = ""
	}
	return &http.Client{Transport: httpTransport}
}

newHTTPClient主要是新建一个HTTPClient(就是建立一个网络连接),在方法中先新建一个Transport结构类型的httpTransport实例。

Transport结构类型:

type Transport struct {    
    Proxy func(*Request) (*url.URL, error)              // Proxy指定一个对给定请求返回代理的函数。  
    Dial func(network, addr string) (net.Conn, error)   // Dial指定创建TCP连接的拨号函数。如果Dial为nil,                                                         // 会使用net.Dial。
    TLSClientConfig *tls.Config                         // TLSClientConfig指定用于tls.Client的TLS配置信息                                                        // 如果该字段为nil,会使用默认的配置信息。  
    TLSHandshakeTimeout time.Duration                    
    DisableKeepAlives bool                              
    DisableCompression bool                             
    MaxIdleConnsPerHost int                             
    ResponseHeaderTimeout time.Duration                 
}

接着对URL的scheme进行判断,如果是unix(也就是访问由docker监听的unix套接字),那么进入case "unix",否则进入默认的default。(能传输到这里的一般是unix、http和https)

Example: unix:///var/run/docker.sock

case "unix": 先新建一个socketPath为URL中Path的内容(如上例子中u.path=/var/run/docker.sock), 接着新建网络连接的拨号方法unixDial,即要赋值给httpTransport实例中的Dial方法。在unixDial方法中调用net包中的DialTimeout方法实现采用超时的网络连接。

func DialTimeout(network, address string, timeout time.Duration) (Conn, error)
即
net.DialTimeout("unix", "/var/run/docker.sock", timeout)
举例
conn, err := net.DialTimeout("tcp", "google.com:80", timeout)

最后返回一个Client结构类型实例表示HTTP客户端。

Client结构类型:

type Client struct {    
    Transport RoundTripper     // Transport指定执行独立、单次HTTP请求的机制。
    CheckRedirect func(req *Request, via []*Request) error
    Jar CookieJar             // Jar指定cookie管理器。
    Timeout time.Duration}

最后返回NewDockerClientTimeout方法中,httpClient建立完成,接着返回一个建立完成的DockerClient结构类型实例。

DockerClient结构类型:

type DockerClient struct {
	URL           *url.URL
	HTTPClient    *http.Client
	TLSConfig     *tls.Config
	monitorEvents int32
}

至此DockerClient创建完成。

2. 发送请求处理

a. doRequest()

func (client *DockerClient) doRequest(method string, path string, body []byte, headers map[string]string) ([]byte, error) {
	b := bytes.NewBuffer(body)
	req, err := http.NewRequest(method, client.URL.String()+path, b)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Content-Type", "application/json")
	if headers != nil {
		for header, value := range headers {
			req.Header.Add(header, value)
		}
	}
	resp, err := client.HTTPClient.Do(req)
	if err != nil {
		if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil {
			return nil, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
		}
		return nil, err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode == 404 {
		return nil, ErrNotFound
	}
	if resp.StatusCode >= 400 {
		return nil, Error{StatusCode: resp.StatusCode, Status: resp.Status, msg: string(data)}
	}
	return data, nil
}

doRequest方法完成发送请求的工作,比如你想获得docker的信息,那么可以通过doRequest方法发送“GET”请求。下面介绍doRequest方法的具体实现。

b := bytes.NewBuffer(body)
方法原型:
func NewBuffer(buf []byte) *Buffer

NewBuffer使用buf(即body)作为初始内容创建并初始化一个Buffer,本方法用于创建一个用于读取已存在数据的buffer(即b)。

req, err := http.NewRequest(method, client.URL.String()+path, b)
方法原型:
func NewRequest(method, urlStr string, body io.Reader) (*Request, error)

NewRequest使用指定的方法、网址和可选的主题创建并返回一个新的*Request(即req)。Request类型代表一个服务端接收到的或者客户端发送出去的HTTP请求。比如上面所说的一个例子:

curl GET http://127.0.0.1:4243/containers/json

那么method=GET, urlStr=http://127.0.0.1:4243/containers/json , body=nil。

Request结构类型:

type Request struct {
    Method   string    //Method指定HTTP方法(GET,POST,PUT等)。对客户端,""代表GET。
    URL   *url.URL     //URL在服务器端表示被请求的URL,在客户端表示要访问的URL。
    Proto   string
    ProtoMajor   int
    ProtoMinor   int
    Header   Header      //Header字段表示HTTP请求的头域。
    Body   io.ReadCloser   //Body是请求的主体。
    ContentLength   int64
    TransferEncoding   []string
    Close   bool
    Host   string
    Form   url.Values
    PostForm   url.Values
    MultipartForm   *multipart.Form
    Trailer   Header
    RemoteAddr   string
    RequestURL   string
    TLS   *tls.ConnectionState
}

具体的各个字段详细解释可以参考帮助文档或者访问下面一个网址:

帮助文档翻译版:http://git.oschina.net/liudiwu/pkgdoc(或者:http://mygodoc.oschina.mopaas.com

Go包方法使用:https://github.com/astaxie/gopkg 。

req.Header.Add("Content-Type", "application/json")
if headers != nil {
	for header, value := range headers {
		req.Header.Add(header, value)
	}
}
方法原型
type Header map[string][]string
func (h Header) Add(key, value string)

Add方法添加键值对到req的Header字段,header字段即HTTP请求的头域。

resp, err := client.HTTPClient.Do(req)
if err != nil {
	if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil {
		return nil, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
	}
	return nil, err
}
方法原型
func (c *Client) Do(req *Request) (resp *Response, err error)

Do方法发送请求,返回HTTP回复。

defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
	return nil, err
}
if resp.StatusCode == 404 {
	return nil, ErrNotFound
}
if resp.StatusCode >= 400 {
	return nil, Error{StatusCode: resp.StatusCode, Status: resp.Status, msg: string(data)}
}
return data, nil
方法原型
func ReaderAll(r io.Reader) ([]byte, error)

ReaderAll方法从请求返回的resp的Body中读取数据知道EOF活着遇到error,返回读取的数据和遇到的错误。并对返回的HTTP状态码进行判断,最后返回数据并关闭resp.Body。

Response结构类型:

type Response sctuct {
    Status  string
    StatusCode  int   
    Proto  string
    ProtoMajor  int
    ProtoMinor  int
    Header  Header
    Body  io.ReadCloser
    ContentLength  int64
    TransferEncoding  []string
    Close  bool
    Trailer  Header
    Request  *Request
    TLS  *tls.ConnectionState
}

总结:上面是DockerClient中主要的建立连接的方式,对于我这样的初学者来说这个项目起到基础的帮助作用,对于开发docker管理项目起到帮助。

参考资料:

1.https://docs.docker.com/reference/api/docker_remote_api/

2.https://github.com/samalba/dockerclient

3.http://git.oschina.net/liudiwu/pkgdoc

4.http://mygodoc.oschina.mopaas.com

5.https://github.com/astaxie/gopkg



© 著作权归作者所有

共有 人打赏支持
clearraining
粉丝 0
博文 1
码字总数 2196
作品 0
厦门
加载中

评论(1)

clearraining
clearraining
82
Kitematic和DockerCLI如何无缝对接

介绍 Kitematic是一个 Docker GUI 工具,它可以在 Mac 和Windows上更快速、更简单的运行Docker。Docker官方表示,Kitematic是其生态系统中成长起来的一个非常棒的项目。 Kitematic简化了安装...

Mrexamo
2015/08/12
893
0
Docker配置文件在Ubuntu中不起作用的解决办法

环境 1. OS 版本: Ubuntu 16.04 LTS 2. Docker版本: Docker version 1.11.2, build b9f10c9 问题描述 最近想使用Docker的Remote API,即使用REST API的形式访问、操作Docker,按照网上的几篇...

风摆残荷
2016/09/04
85
0
Docker学习笔记八 使用Docker API

8.1 Docker API 在Docker生态系统中一共有三种API: Registry API:提供了与Docker Registry集成的功能; Docker Hub API:提供了与Docker Hub集成的功能; Docker Remote API:提供了与Doc...

一万
2016/07/15
48
0
一种新的进入容器的方式: WebSocket + Docker Remote API

众所周知,容器是基于操作系统内核的一种轻量级的虚拟化技术。其可以类比于虚拟机,但其本身并不是虚拟机。在传统的虚拟机使用场景中,每个用户都会通过堡垒机,根据自己被分配的权限,登录某...

xiaomin0322
01/15
0
0
Jenkins & Docker 持续集成实践

前言 持续集成(CI/CD)是一种软件开发实践。用于帮助团队成员频繁、快速的集成,测试他们的工作成果,以尽快发现集成错误。 更频繁、更早的集成意味着更早的发现问题。通过持续集成,及时发现...

English0523
2017/12/25
0
0
Jenkins & Docker 持续集成实践

Jenkins & Docker 持续集成实践 运维生存时间 - 运维生存时间2017-12-109 阅读 jenkinsdockerLinux 发表评论 A+ 所属分类: Linux 前言 持续集成(CI/CD)是一种软件开发实践。用于帮助团队成员...

运维生存时间 - 运维生存时间
2017/12/10
0
0
Docker on Mac上的Remote API 远程控制

Docker提供了Remote API,可以通过REST接口进行Docker服务的控制,包括pull/push等所有操作,结果与本机的操作完全一样。使用Docker Remote API可以通过脚本进行Docker集群的自动化控制。 但...

openthings
2016/10/29
491
0
Docker自发现注册服务regd研发

前言 [技术源于艺术, 艺术源于生活] 1) 这是我第一次发布程序相关的技术文章, 10年前发表过很多关于3dsmax和maya的技术文章 2) 有人无端转载我的文章, 所以这里留一个我的联系方式, 欢迎讨论...

funwun
2016/05/16
766
2
Python操纵Docker Remote API实现自动化

Docker提供了Remote API,可以通过REST接口进行Docker服务的控制,包括pull/push等所有操作,结果与本机的操作完全一样。使用Docker Remote API可以通过脚本进行Docker集群的自动化控制。 1、...

openthings
2016/10/28
120
0
『干货​』Go语言使用Docker Remote API ,举个栗子!

Docker Remote API是一个取代远程命令行界面(rcli)的REST API。我们使用命令行工具cURL来处理url相关操作。cURL可以发送请求、获取以及发送数据、检索信息。通过Docker Remote API,我们可...

shev
2017/12/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

10.28 rsync工具介绍 , rsync常用选项, rsync通过ssh同步

rsync远程同步 重点!重点!!重点!!! 例子 • rsync -av /etc/passwd /tmp/1.txt • rsync -av /tmp/1.txt 192.168.188.128:/tmp/2.txt rsync格式 • rsync [OPTION] … SRC DEST • rs......

Linux_老吴
11分钟前
0
0
iis php 环境搭建,非常详细的教程

准备篇 一、环境说明: 操作系统:Windows Server 2016 PHP版本:php 7.1.0 MySQL版本:MySQL 5.7.17.0 二、相关软件下载: 1、PHP下载地址: http://windows.php.net/downloads/releases/ph...

T_star
13分钟前
0
0
Day35 rsync通过服务同步

rsync通过服务同步 rsyncd.conf配置文件详解 port:指定在哪个端口启动rsyncd服务,默认是873端口。 log file:指定日志文件。 pid file:指定pid文件,这个文件的作用涉及服务的启动、停止等...

杉下
19分钟前
0
0
【最新最全】为 iOS 和 Android 的真机和模拟器编译 Luajit 库

编译 Luajit 库,的确是一个挑战。因为官网的教程,在当前版本的 Xcode 和 NDK 环境中,已经不适用了。以前只是编译了适用于真机的 Luajit 库。最近在尝试编译模拟器 Luajit 库,就顺便梳理了...

ios122
19分钟前
0
0
rsync至ssh同步

rsync: 文件同步工具,可实现“增量拷贝”;使用yum安装rsync包 常用选项:-a=-rtplgoD (-r同步目录,-t保持文件的时间属性,-p保持文件的权限属性,-l保持软连接,-g保持文件的属组,-o保持...

ZHENG-JY
24分钟前
0
0
TradingView 学习笔记

#前言 公司最后需要使用TradingView展示K线图走势。由于之前没接触过,拿到文档时一脸蒙逼。还好找到二篇文章+Demo代码,直接改改就行了。 #被批 由于上面的懵懂,有个问题困扰4个小时没解决...

hihubs
24分钟前
0
0
10.28 rsync工具介绍~10.31 rsync通过ssh同步

rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。rsync使用所谓的“rsync算法”来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而...

洗香香
27分钟前
1
0
php如何使用JSON-RPC查找以太坊中的最新块哈希hash值?

我用PHP中开发了一个以太坊块资源管理器,并成功地与我的服务器Geth节点建立了JSON-RPC通信。然而,当我试图找出最后一个区块时,我陷入了困境。我在https://ethereum.gitbooks.io/frontier...

智能合约
33分钟前
1
0
卷积为什么要旋转180度

参考《最容易理解的对卷积(convolution)的解释》 https://blog.csdn.net/bitcarmanlee/article/details/54729807 这篇博客详细讲解了“卷积”,提及了为什么要反转180度,我简述下。 1.卷积的...

datadev_sh
36分钟前
0
0
【2018.07.18学习笔记】【linux高级知识 20.23-20.26】

20.23/20.24/20.25 告警系统邮件引擎 告警系统邮件引擎由两个文件组成,放在/mon/mail/目录下:mail.py、mail.sh mail.py:是邮件的核心python脚本,邮件功能的实现mail.sh:是告警邮件系统...

lgsxp
41分钟前
16
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部