Docker新手入门之八:Docker API详解
2018-02-19T16:38:47
4531
0
0
#### Docker本身提供了强大的API功能。
#### 我们可以通过访问Docker API来对Docker服务进行管理。
#### 在本章中,我们将会学习如何使用Docker API以及在Python中如何更加高效的使用Docker API。
## Docker API
在Docker的生态系统中,存在下列三种API:
1. Reistry API:与存储Docker镜像的Registry相关的功能。
2. Docker Hub API:与Docker Hub相关的功能
3. Docker Remote API:与Docker守护进程相关的功能。
其中,Docker Remote API是使用最为频繁的API类型,后续我们也将针对此类API展开讲解。
## 启动Remote API
Remote API主要用于远程访问Docker守护进程从而下达指令的。
因此,我们在启动Docker守护进程时,需要添加`-H`参数并指定开启的访问端口。
通常,我们可以通过编辑守护进程的配置文件来实现。
不过对于不同操作系统而言,守护进程启动的配置文件也不尽相同:
- Ubuntu系统:`/etc/default/docker`文件
- Centos系统:`/etc/sysconfig/docker`文件
在该配置文件最后,添加内容如下:
```
OPTIONS='-H=tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock'
```
修改完成后执行如下命令,重启Docker守护进程:
```
systemctl stop docker
systemctl start docker
```
此时,我们可以在其他机器上执行如下命令来测试一下:
```
docker -H example.com:2375 info
```

## 测试Remote API
上面的试验中,我们已经确认了与Docker守护进程之间的连通性。
下面,我们来使用一些Remote API。
```bash
curl http://example.com:2375/info
```
从返回结果看,我们可以得到类似的`docker info`时的JSON格式的数据。
### 通过API管理Docker镜像
调用`/images/json`接口可以获取镜像列表:
```bash
curl http://example.com:2375/images/json | python -mjson.tool
```

Ps:通过`python -mjson.tool`可以将JSON数据格式化显示。
### 通过API管理Docker容器
调用`/containers/json`接口可以获取正在运行中的容器列表:
```bash
curl http://example.com:2375/containers/json | python -mjson.tool
```

如果想要查询全部的容器(包含不是正在运行的容器)时,可以调用如下接口:
```bash
curl http://example.com:2375/containers/json?all=1 | python -mjson.tool
```
此外,我们还可以使用`/containers/create`以及`/containers/start`来创建和启动容器,从而实现`docker run`的功能。
但是在此处,我们并不对其进行展开描述。因为在本文后续内容中,会详细描述如果利用Python来调用Remote API,这种方式则更加方便和强大。
## 对Docker Remote API进行认证
之前我们已经学到了可以通过Docker Remote API来控制Docker服务。
但是,细心的同学应该已经发现了,在连接的过程中并没有认证机制。
也就是说任何人只要知道了Docker API的地址和端口都可以用于控制Docker服务,而这样则大大增加了服务的风险。
接下来,我们将会学习如何给Docker Remote API添加认证机制。
### 创建所需的CA证书
```
cd /etc/docker
openssl genrsa -aes256 -out ca-key.pem 4096
# 设置证书密码
```
完成该步骤后,我们创建了一个`ca-key.pem`文件。这个文件就是我们的CA密钥。
下面,我们需要继续创建我们的CA证书。
```
openssl req -new -x509 -days 3650 -key ca-key.pem -sha256 -out ca.pem
# 输入一系列相关信息,可省略部分直接输入.
# 国家:CN
# 省:.
# 市:.
# 公司:.
# 组织:.
# Common Name:网站地址
# Email Address:.
```
### 创建服务端证书、签名请求和密钥
```
# 创建证书
openssl genrsa -out server-key.pem 4096
# 设置证书密码
# 创建签名
openssl req -sha256 -new -key server-key.pem -out server.csr
# 输入一系列相关信息,可省略部分直接输入.
# 国家:CN
# 省:.
# 市:.
# 公司:.
# 组织:.
# Common Name:*
# Email Address:.
# 生成服务器证书
openssl x509 -req -days 3650 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
```
### 修改Docker守护进程配置文件
在启动参数OPTIONS中添加如下内容:
```bash
-H=tcp://0.0.0.0:2376 # 修改端口号为2376
-H=unix:///var/run/docker.sock
--tlsverify
--tlscacert=/etc/docker/ca.pem
--tlscert=/etc/docker/server-cert.pem
--tlskey=/etc/docker/server-key.pem
```
修改完成后重启Docker守护进程:
```
systemctl stop docker && systemctl start docker
```
### 创建客户端证书和密钥
```
# 创建证书
openssl genrsa -out key.pem 4096
# 设置证书密码
# 创建签名
openssl req -new -key key.pem -out client.csr
# 输入一系列相关信息,可省略部分直接输入.
# 国家:CN
# 省:.
# 市:.
# 公司:.
# 组织:.
# Common Name:*
# Email Address:.
# 生成服务器证书
openssl x509 -req -days 3650 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem
# 删除无效文件并最小化权限
rm -v client.csr server.csr
chmod -v 0400 ca-key.pem key.pem server-key.pem
chmod -v 0444 ca.pem server-cert.pem cert.pem
```
### 配置Docker客户端使用证书
将`ca.pem`,`client-cert.pem`以及`client-key.pem`这三个文件复制到`~/.docker/文件夹下即可,因为默认在会该文件夹下寻找证书。
```
cp ca.pem ~/.docker
cp cert.pem ~/.docker
cp key.pem ~/.docker
```
下面,我们来测试一下:
```
curl https://example.com:2376/info --cert ./cert.pem --key ./key.pem -k
```
如果能够正常显示结果,表示配置完成,一切正常了!
## Python调用Docker API
对于原生Docker Remote API而言,虽然功能很强大,但是使用起来并不是十分的方便。
为了简化Docker Remote API的使用,Python针对Docker API进行了封装,提供了一套完整的Python第三方库:`docker`,专门用于操作调用Docker服务。
接下来,我们将会详细详解如何使用Python的第三方库来调用Docker。
### 安装第三方库
第一步,当然是安装Python第三方库啦!我们可以直接使用Python自带的包管理工具进行安装:
```
pip install docker
```
### 试用一下吧:
创建一个`docker_api.py`的文件,修改文件内容如下:
```
import docker
client = docker.DockerClient(base_url='tcp://example.com:2375', version="auto")
client.containers.run("ubuntu", "echo hello world")
```
这是一个最简单的例子,我们先来了解一下。
第一行表示引入第三方库`docker `。
第二行用于配置Docker服务端的基本信息,次数包含了base_url(Docker服务端的地址)以及version。
Ps:version设置为"auto"可以自动检查Docker API的版本。
第三行则是相当于运行了一个`docker run ubuntu echo hello world`的命令。
下面,我们逐步来进行扩展。
在之前的内容中,我们讲解了如何对docker remote API添加认证机制。
如果对docker remote API添加了TLS的认证机制后,此处则无法这样连接至Docker服务端了,因为我们同样需要添加认证信息。添加认证信息的方式如下:
```
import docker
tls_config = docker.tls.TLSConfig(
client_cert=(r'e:\git\log\cert.pem', r'e:\git\log\key.pem'),
verify=False
)
client = docker.DockerClient(base_url='tcp://example.com:2376', tls=tls_config, version="auto")
client.containers.run("ubuntu", "echo hello world")
```
观察一下,此处我们修改了三个位置。
首先是创建了`tls_config`。其中包含了客户端的密钥信息。
其次是修改了`base_url`的端口号,因为通过TLS认证服务的端口会设置为2376。
第三点是在`DockerClient`中增加了一个参数`tls`,其值为我们刚创建的变量`tls_config`。
最后,我们在来了解一下针对容器运行时,复杂的参数如何进行传递的问题。
`client.containers.run`的函数格式如下:
```
run(image, command=None, **kwargs)
```
其中,第一个参数为镜像名称(必填),第二个参数为执行命令,默认为空,可以是字符串或者列表(同`docker run`时的命令),**kwargs表示一组参数,核心参数见下表。
参数标识|类型|含义
-|-|-
detach | Bool | 是否以后台服务的方式运行
entrypoint | 字符串或者列表 | 同`docker run`
hostname | 字符串 | 主机名称
links | 字典 | 同`docker run`
name | 字符串 | 容器名称
ports | 字典 | 端口映射 {8000: 80}表示容器的8000端口映射到宿主机的80端口
remove | Bool |运行结束后是否自动删除
restart_policy | 字典 | 重启策略
user | 字符串 | 运行用户
volumes | 字典 | 卷映射 示例:{'/home/user1/': {'bind': '/mnt/vol2', 'mode': 'rw'}, '/var/www': {'bind': '/mnt/vol1', 'mode': 'ro'}}
working_dir | 字符串 | 工作目录
runtime | 字符串 | 容器的运行时间
对于`client.containers.run`的函数的返回值,当`detach=False`时,返回值是运行过程中的日志,而当`detach=True`时,返回值是Container对象。
更多关于Python第三方库操作Docker的内容可以参考官方手册:https://docker-py.readthedocs.io/en/stable/index.html