一、REST简介
Docker API是RESTful的,那么什么是REST?REST的英文翻译为Representational State Transfer,大多数中文直接翻译为“表述性状态转移”,可以忽略这个翻译。一般来说,只要一个架构的设计满足REST,就可以称之为RESTful的架构,Docker API的设计也是满足REST风格的。
Docker API的访问可以由wget或curl等HTTP客户端或HTTP库访问,如下,以JSON数据格式放回名我为centos的镜像信息:
[root@k8s-m1 ~]# echo -e "GET /images/centos/json HTTP/1.0\r\n" |nc -U /var/run/docker.sock
HTTP/1.0 200 OK
Api-Version: 1.40
Content-Type: application/json
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.15 (linux)
Date: Mon, 05 Jun 2023 12:45:27 GMT{"Id":"sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6","RepoTags":["332772194/centos:latest","centos:latest"],"RepoDigests":["332772194/centos@sha256:a1801b843b1bfaf77c501e7a6d3f709401a1e0c83863037fa3aab063a7fdb9dc","centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177"],"Parent":"","Comment":"","Created":"2021-09-15T18:20:05.184694267Z","Container":"9bf8a9e2ddff4c0d76a587c40239679f29c863a967f23abf7a5babb6c2121bf1","ContainerConfig":{"Hostname":"9bf8a9e2ddff","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/bin/bash\"]"],"Image":"sha256:f5b050f177fd426be8fe998a8ecf3fb1858d7e26dff4080b29a327d1bd5ba422","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{"org.label-schema.build-date":"20210915","org.label-schema.license":"GPLv2","org.label-schema.name":"CentOS Base Image","org.label-schema.schema-version":"1.0","org.label
......
二、Docker API种类
docker提供如下三类RESTful API,详情可阅读官方文档:https://docs.docker.com/engine/api/
Docker engine(remote) API: 诸如docker run等操作最终都是通过调用Docker Remote API向Docker daemon 发起请求的,使用它我们可以远程操作docker容器,更重要的是可以通过程序自动化运维docker进程。
Docker Registry API:与镜像存储有关的操作可以通过Docker Registry API来完成,可以自由的自动化、程序化的管理你的镜像仓库。
Docker Hub API:用户管理等操作可以通过Docker Hub API来完成,docker hub是使用校验和公共 namespaces 的方式来存储账户信息、认证账户、进行账户授权。API同时也允许操作相关的用户仓库和 library 仓库。类似GitHub的管理,本节暂不进行讨论。
三、API使用前准备
在体验之前,我们需要开启docker rest api。具体开启的方法:
[root@k8s-m1 ~]# vim /usr/lib/systemd/system/docker.service
在 ExecStart=/usr/bin/dockerd 后面直接添加 -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock (注意端口2375自己随便定义,跟当前服务器已使用端口不冲突即可)[root@k8s-m1 ~]systemctl daemon-reload
[root@k8s-m1 ~]systemctl restart docker
[root@k8s-m1 ~]# netstat -anp|grep 2375
tcp6 0 0 :::2375 :::* LISTEN 26074/dockerd
#命令行执行测试:
[root@k8s-m1 ~]# curl 127.0.0.1:2375/info | python -mjson.tool
四、如何操作Docker API
最简单的curl方式,centos下没有的话可以直接用yum安装
比如我们查看docker的images详细信息,就可以直接用curl 来调取:
[root@k8s-m1 ~]# curl 127.0.0.1:2375/info | python -mjson.tool
我们可以在命令后面加个 python -mjson.tool 格式化输出,方便查看,不加的话看起来比较头疼。
查看所有containers容器:
[root@k8s-m1 ~]# curl -X GET http://127.0.0.1:2375/containers/json | python -mjson.tool
#注意如果服务器容器太多,输出会很长#测试创建一个containers容器:
#这里创建一个mysql数据库的容器,设置了密码是123456,容器内监听端口是3306,映射到宿主机的3307端口,方便大家区分。
[root@k8s-m1 ~]# curl -X POST -H "Content-Type: application/json" -d '{"Image": "mysql:5.7","Env": ["MYSQL_ROOT_PASSWORD=123456"],"ExposedPorts": {"3306/tcp": {}},"HostConfig": {"PortBindings": {"3306/tcp": [{"HostIp": "","HostPort": "3307"}]}},"NetworkSettings": {"Ports": {"3306/tcp": [{"HostIp": "0.0.0.0","HostPort": "3307"}]}}
}' http://127.0.0.1:2375/containers/create
{"Id":"6b0a6c856d0f425767a4286e3623796f28aa124bd59727733b317a0c62cf2915","Warnings":[]}
#启动/停止/重启 一个containers容器:
[root@k8s-m1 ~]#curl -X POST http://127.0.0.1:2375/containers/6b0a6c856d0f/start (注意这都是POST方法)
[root@k8s-m1 ~]#curl -X POST http://127.0.0.1:2375/containers/6b0a6c856d0f/stop (注意这都是POST方法)
[root@k8s-m1 ~]#curl -X POST http://127.0.0.1:2375/containers/6b0a6c856d0f/restart (注意这都是POST方法)
#使用时注意修改容器id
使用Remote docker daemon,其他服务需指定docker daemon地址
[root@k8s-m2 ~]#docker -H tcp://192.168.2.140:2375 version
[root@k8s-m2 ~]# docker -H tcp://192.168.2.140:2375 ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b8c23fa42383 mysql:5.7 "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 3306/tcp, 33060/tcp zealous_heisenberg
[root@k8s-m2 ~]# docker -H tcp://192.168.2.140:2375 images
......
[root@k8s-m2 ~]# curl http://192.168.2.140:2375/containers/json | python -mjson.tool
......
[root@k8s-m2 ~]# curl http://192.168.2.140:2375/images/json | python -mjson.tool
......
浏览器也可以访问:
比如想要查看版本,直接 http://ip:2375/version
其他的操作入口,请参考官网:
https://docs.docker.com/engine/api/v1.41/
#其他版本请修改版本号
五、对Docker Remote API进行认证
通过上面方法,只要知道了Docker API的地址和端口都可以用于控制Docker服务,而这样则大大增加了我们业务的风险。
下面,我们将会测试如何给Docker Remote API添加认证机制。
#创建所需的CA证书
[root@k8s-m1 ~]# cd /etc/docker/
[root@k8s-m1 docker]# openssl genrsa -aes256 -out ca-key.pem 4096
Generating RSA private key, 4096 bit long modulus
.........................++
...++
e is 65537 (0x10001)
Enter pass phrase for ca-key.pem:
Verifying - Enter pass phrase for ca-key.pem:[root@k8s-m1 docker]# openssl req -new -x509 -days 3650 -key ca-key.pem -sha256 -out ca.pem
Enter pass phrase for ca-key.pem:
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:SC
Locality Name (eg, city) [Default City]:CD
Organization Name (eg, company) [Default Company Ltd]:***
Organizational Unit Name (eg, section) []:\*\*\*
Common Name (eg, your name or your server's hostname) []:docker.margu.com
Email Address []:********@qq.com#创建服务端证书、签名请求
[root@k8s-m1 docker]# openssl genrsa -out server-key.pem 4096
Generating RSA private key, 4096 bit long modulus
........++
....................................................................++
e is 65537 (0x10001)
[root@k8s-m1 docker]# openssl req -sha256 -new -key server-key.pem -out server.csr
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:SC
Locality Name (eg, city) [Default City]:CD
Organization Name (eg, company) [Default Company Ltd]:***
Organizational Unit Name (eg, section) []:\*\*\*
Common Name (eg, your name or your server's hostname) []:docker.margu.com
Email Address []:*****@qq.com Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:margu
An optional company name []:****
[root@k8s-m1 docker]# openssl x509 -req -days 3650 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
Signature ok
subject=/C=CN/ST=SC/L=CD/O=wst/OU=yw/CN=docker.margu.com/emailAddress=******@qq.com
Getting CA Private Key
Enter pass phrase for ca-key.pem:#修改配置
[root@k8s-m1 docker]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server-cert.pem --tlskey=/etc/docker/server-key.pem[root@k8s-m1 docker]# systemctl daemon-reload
[root@k8s-m1 docker]# systemctl restart docker
[root@k8s-m1 docker]# scp ca* server* root@k8s-m2:/root#接下来在k8s-m2上操作
# 创建证书
[root@k8s-m2 ~]#openssl genrsa -out key.pem 4096
# 创建签名
[root@k8s-m2 ~]#openssl req -new -key key.pem -out client.csr
# 生成服务器证书
[root@k8s-m2 ~]#openssl x509 -req -days 3650 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem
[root@k8s-m2 ~]#rm -v client.csr server.csr
[root@k8s-m2 ~]#chmod -v 0400 ca-key.pem key.pem server-key.pem ca.pem server-cert.pem cert.pem
[root@k8s-m2 ~]#cp ca.pem cert.pem key.pem ~/.docker
#测试API的可用性
[root@k8s-m2 ~]#curl https://192.168.2.140:2375/images/json --cert ./cert.pem --key ./key.pem -k | python -mjson.tool
六、高级应用:利用Python调用API接口
Docker给python提供了一个非常强大的库,名字就叫做docker。我们可以参考文档学习如何操作。
官网是:https://docker-py.readthedocs.io/en/stable/
1)、安装Python第三方库
#首先安装pip,这只是其中一种方法,其他自行测试
[root@k8s-m1 docker]#wget https://bootstrap.pypa.io/pip/3.6/get-pip.py
[root@k8s-m1 docker]#python get-pip.py
[root@k8s-m1 docker]#pip3 install --upgrade pip
[root@k8s-m1 docker]#pip3 installe docker
[root@k8s-m1 docker]#pip list
2)开始使用
但由于通过上面的安装,我的python环境还是有点小问题,我就直接在pycharm上测试的:
import docker
client=docker.DockerClient(base_url='tcp://192.168.2.140:2375',version='auto')
client.containers.run("centos","/bin/bash")
第一行表示引入第三方库docker。
第二行用于配置Docker服务端的基本信息,包含了base_url(Docker服务端的地址)以及version(auto可以自动检查docker的版本)。
第三行则是相当于运行了一个docker run centosecho hello world的命令。
检查:到相应的服务器检查有一个容器被创建。
或者安装ipython测试
[root@k8s-m1 ~]#yum install -y python-ipython-console
[root@k8s-m1 ~]# ipython
Python 2.7.5 (default, Jun 28 2022, 15:30:04)
Type "copyright", "credits" or "license" for more information.IPython 3.2.3 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.In [1]: import dockerIn [2]: client=docker.DockerClient(base_url='http://192.168.2.140:2375',version='auto')In [3]: client.containers.run("centos",'echo hello world')
Out[3]: 'hello world\n'
进阶使用(怎么执行无所谓,能用就行)
#查看的相关操作
import docker
client=docker.DockerClient(base_url='http://192.168.2.140:2375',version='auto')
client.images.list() # 类似docker images命令,显示image的信息列表
client.containers.list() # 类似docker ps命令
client.containers.list(all=True) # 类似docker ps -a命令
container = client.containers.get(container_id) # 获取daodocker容器,这里container_id 是你要输入的具体容器id
container.start() #启动容器
#端口映射
import docker
client=docker.DockerClient(base_url='http://192.168.2.140:2375',version='auto')
container = client.containers.run('mysql/mysql-server:5.7',ports={'3306/tcp': 3306}, auto_remove=True, name='python_mysql',detach=True)
#通过调用api接口创建一个名为python_mysql的mysql容器,后面的端口为映射到宿主机的端口
#查看对应容器对象的方法和属性
print(dir(container))
print(container.short_id)
Docker registry API 请自行测试