使用 Python 玩转 Docker安装 Docker SDK for Python 我们都知道,SDK 从某个角度来
安装 Docker SDK for Python
我们都知道,SDK 从某个角度来说就是对 API 的封装,以方便开发者使用,Docker SDK 官方支持的语言总共有两种:
-
Go
-
Python
其余语言则是社区开发的非官方版本,而这里我们选用的是 Python,直接从 PyPI 安装即可:
pip install docker
初始化 Docker client
使用 Python SQL driver 类的包我们都需要先创建一个“连接”,比如:
import pymysql
connection = pymysql.connect(
host='localhost',
user='user',
password='passwd',
database='db')
同理,要操作 Docker Engine 也需要先创建一个“客户端连接”,毕竟 Docker 是典型的 client/server 架构,我们平常使用的 Docker CLI 就是一个 Docker client,而 server 端则是 Docker Engine,又称为 Docker daemon。
import docker
client = docker.from_env()
绝大部分的 Docker 操作,都是从这个 client 开始。初始化 client 连接非常简单,只需要from_env()
一行解决,不过这里有一个需要注意的点,那就是 Docker daemon 所在的连接地址——DOCKER_HOST
环境变量。
事实上,from_env()
会自动使用相关环境变量,来获取 Docker daemon 的连接地址。如果没有设置,那么默认会连接到本机上的地址,通常是unix://var/run/docker.sock
。
和 Docker CLI 相同,from_env()
会使用这三个环境变量:
-
DOCKER_HOST
-
DOCKER_TLS_VERIFY
-
DOCKER_CERT_PATH
通常我们只需要关注第一个——DOCKER_HOST
——即可。
DOCKER_HOST 环境变量
平常我们在本机安装 Docker,实际上是同时安装了 Docker CLI 和 Docker Engine,启动 Docker Engine 在本机启动一个进程,即为 Docker daemon。
注意:一般提到 Docker host,通常指的是 Docker network 中的 host network,和这里的
DOCKER_HOST
环境变量所代表的意义并不相同。
因为 Docker client 和 Docker Engine 都安装在同一台主机上,此时DOCKER_HOST
地址通常是像unix://var/run/docker.sock
或tcp://127.0.0.1:2375
这类的本机路径,使用from_env()
可以轻松创建 client 连接。
当然,Docker Engine 必须先启动。
Remote Docker daemon
但如果想要连接的 Docker daemon 是位于远程主机,通过from_env()
创建连接时,就要先设置DOCKER_HOST
这个环境变量,以取代 SDK 提供的连接默认值。换句话说,在连接 localhost 时,这个变量可以不设置,而在连接远程主机时,就必须要有。
最简单的方式如下:
import os
import docker
os.environ["DOCKER_HOST"] = 'tcp://22.22.22.22:2375'
client = docker.from_env()
但最好还是直接在
.env
之类的环境设置文件把环境变量值设置好,并在 app 中获取。在代码中明示任何帐号、密码、内部主机地址都不妥,应尽量避免。
如果远程主机要求使用 SSL 连接,则连接地址要设置在DOCKER_TLS_VERIFY
。
from_env()
是 Docker SDK 提供创建连接的捷径,如果想使用更完整的参数,则要直接调用DockerClient
类型来创建连接对象(实例),如下:
import docker
client = docker.DockerClient(base_url='unix://var/run/docker.sock')
这部分请直接参考官方文档,大部分情况使用from_env()
应该已经足够。
Docker socket 权限问题
即使是通过本机上的 socket 连接本机的 Docker daemon,程序也可能遇到连接问题,通常是程序 app 的执行权限不符合主机上 Docker socket 的要求,会出现类似下面的错误讯息:
Error while fetching server API version: ('Connection aborted.', PermissionError(13, 'Permission denied'))
此时可能要修改var/run/docker.sock
文件或 app 本身的权限,而这样做是否安全,需具体考量,这里只是点出这个潜在问题。
容器操作
Docker 最常见使用的就是容器操作,我们来大概了解一下。
创建并启动容器:containers.run
先看个例子:
client.containers.run('alpine', command='echo hello world', ports={'2222/tcp': 3333})
方式是使用 SDK 中containers
模块的run
方法(method),再看一下官方文档中run
的使用说明:
run(image
, command=None
, **kwargs
)
Run a container. By default, it will wait for the container to finish and return its logs, similar to
docker run
.
简单来说,执行run
的结果,即是依据给定的参数,来创建相对应的Container
对象,和你使用 CLI 执行docker container run
指令很类似。
从官方文档中可知run
方法具有两个位置参数:image
与command
。image
调用时一定不可省略,而command
有参数默认值None
,调用时可以省略,位置参数的特色是可以直接按顺序赋值调用,不需使用参数名称,如下:
client.containers.run('alpine', 'echo hello world')
从这上述两个例子可以轻易看出,这里的参数就相当于我们使用 CLI 时的 flag(也是参数啦)!很容易理解与转换,换句话说,本段开头的第一个例子可以理解为下面的 CLI 指令:
docker container run -p 2222:3333 alpine echo hello world
containers
模块的角色相当于 CLI 中的docker container
,了解怎么创建与启动容器后,剩下就是容器的获取与操作问题了。
创建时即获取容器对象:detach=True
程序成功执行containers.run
方法后,容器就会创建及启用,但若想要直接获取该容器对象以进行后续操作,则需要在调用run
方法时加上detach=True
参数,类似于 CLI 中的-d
:
>>> client.containers.run('alpine', detach=True)
<Container '45e6d2de7c54'>
虽然都是 detach 的意思,但 CLI 使用-d
通常是为了不要让容器的 process 占用前景,而这里是程序执行,没有前景占用问题,detach=True
的主要意义在于获取容器。
获取容器并存为变量:
container = client.containers.run('alpine', detach=True)
获取容器对象通常是想要进一步存取该容器的相关信息,比如容器 id、logs 等:
container_id = container.id
logs = container.logs
容器对象的所有属性及方法,请参考官方文档。
获取已存在的容器对象:containers.get
上面讲的是创建的时候顺便获取容器对象,而如果要获取“已存在”的容器,不论容器是否执行中,都可以通过容器 id 或容器名称获取——使用get
方法:
container = client.containers.get('<容器id>')
container = client.containers.get('<容器名称>')
这里的容器 id 和使用 CLI 一样,可以只取前面几位即可,比如只取'45e6'
,只要没有重复的容器 id 就能成功获取,反之则会出 error。不过这毕竟是程序执行,谨慎起见,建议还是不要取太少位,但可以不必是全部。
常用容器操作示例
获取特定容器对象后,才能对它进行操作,这里就只演示一下几个常用的操作即可。
删除容器
container.remove()
container.remove(force=True)
相当于docker container rm
、docker container rm -f
。
启动容器
container.start()
相当于docker container start
。
停止容器
container.stop()
相当于docker container stop
。
小结
可以看出,只要熟悉 CLI 操作指令,使用 SDK 也会很容易上手。可以想见,平常我们通过 CLI 操作 Docker,其实也是内部 SDK 帮你把指令转换为代码再与 Docker daemon 进行交互。
转载自:https://juejin.cn/post/7412672700302737462