文章目录
本篇博客围绕官方提供的python版的docker Engine API(Docker SDK for Python),结合具体示例,详细介绍如何使用python来自动化操作docker。
建议本篇文章同《Docker常用指令汇总》一起食用效果更佳!!!
要与Docker服务器进行通信,首先需要实例化一个客户端,要做到这一点,最简单的方法是调用 from_env()函数 ,当然,如果使用ssh来操作远程的docker,也可以通过实例化 DockerClient 类。
常规client实例化:
# pip install docker
import docker
client = docker.from_env()
使用ssh远程操作docker,初始化client可以这样做:
client = docker.Dockerclient("ssh://username@yourip", use_ssh_client=True)
# 执行之后会让用户输入密码
# base_url(str) -- 指向Docker服务器的URL。例如, unix:///var/run/docker.sock 或 tcp://127.0.0.1:1234
# version(str) -- 要使用的API的版本。设为 auto 自动检测服务器的版本。默认: 1.35
# timeout(int) -- API调用的默认超时时间,单位为秒
# tls(bool or TLSConfig) -- 启用TLS。经过 True 使用默认选项启用它,或将 TLSConfig 对象以使用自定义配置
# user_agent(str) -- 为对服务器的请求设置自定义用户代理
# credstore_env(dict) -- 调用凭据存储进程时覆盖环境变量
# use_ssh_client (bool) -- 如果设置为 True ,通过向ssh客户端发出命令来建立ssh连接。确保在主机上安装并配置了ssh客户端
# max_pool_size (int) -- 要保存在池中的最大连接数
得到的client是一个DockerClient对象,常用的属性及方法有:
| 属性 | 功能 | 备注 |
|---|---|---|
containers | 用于管理服务器上的容器 | 无 |
images | 用于管理服务器上的镜像 | 无 |
close() | 关闭当前连接 | 无 |
events() | 从服务器获取实时事件 | docker events |
info() | 显示系统范围的信息 | docker info |
login() | 使用注册表进行身份验证 | docker login |
version() | 从服务器返回版本信息 | docker version |

client.images是一个ImageCollection对象,用来管理服务器上的镜像,其主要有以下方法:
| 属性 | 功能 | 备注 |
|---|---|---|
list(**kwargs) | 列出服务器上的图像 | docker images |
get(name) | 根据镜像名字来获取镜像 | 无 |
load(data) | 加载镜像 | docker load 需要注意的是,data参数为镜像的二进制数据,而非路径 |
prune(filters=None) | 删除未使用的图像 | 无 |
pull(repository, tag=None, all_tags=False, **kwargs) | 拉取给定名称的镜像并将其返回 | docker pull |
push(repository, tag=None, **kwargs) | 将镜像推送到注册表 | docker push |
remove(*args, **kwargs) | 删除镜像 | docker rmi |
search(*args, **kwargs) | 在Docker Hub上搜索镜像 | docker search |
client.list()
client.images.get('myubuntu:python')
# 加载镜像
with open(image_path, 'rb') as f:
img = client.images.load(f)
img_obj = img[0]
print('Image Info: ', img_obj.short_id, img_obj.tags)
# 拉取最新的ubuntu镜像
image = client.images.pull('ubuntu')
# 如果 tag 是 None 或为空,则设置为 latest
# 如果 all_tags 已设置,则 tag 参数被忽略,并且将拉取所有镜像标签

Image对象是服务器上的映像,其主要有以下方法:
| 属性 | 功能 | 备注 |
|---|---|---|
attrs | 服务器中此对象的原始表示形式 | 无 |
id | 镜像的ID | 无 |
labels | 作为字典的镜像的标签 | 无 |
short_id | 截断为12个字符的图像的ID,加上 sha256: 前缀 | 无 |
tags | 镜像的标签 | 无 |
history() | 显示图像的历史记录 | 无 |
reload() | 再次从服务器加载此对象并更新 attrs 使用新的数据 | 无 |
save(chunk_size=2097152, named=False) | 保存镜像 | docker save |
tag(repository, tag=None, **kwargs) | 将此镜像的标签添加到存储库中 | docker tag |
img = client.images.get('myubuntu:python')
print(img.attrs)
print(img.id)
print(img.labels)
print(img.short_id)
print(img.tags)

client.containers是一个ContainerCollection对象,在服务器上运行和管理容器,其主要有以下方法:
| 属性 | 功能 | 备注 |
|---|---|---|
run(image, command=None, **kwargs) | 运行一个容器,默认情况下,它将等待容器完成并返回其日志 | docker run ,如果 detach 参数是 True ,它将启动容器并立即返回一个 Container 对象,类似于 docker run -d |
create(image, command=None, **kwargs) | 在不启动的情况下创建容器 | docker create |
get(id_or_name) | 按名称或ID获取容器 | docker create |
list(**kwargs) | 列出容器 | docker ps |
prune(filters=None) | 删除停止的容器 | 无 |
下面将详细介绍一下run()函数,主要有以下参数:
image(str) ---- 要运行的映像command(str or list) ---- 要在容器中运行的命令auto_remove(bool) ---- 当容器的进程退出时,在守护程序端启用容器的自动删除cap_add(list of str) ---- 添加内核功能,例如,["SYS_ADMIN", "MKNOD"]cap_drop(list of str) ---- 放弃内核功能cpu_count(int) ---- 可用CPU数(仅限windows)cpu_percent(int) ---- 可用CPU的可用百分比(仅限windows)cpu_period(int) ---- 以微秒为单位的CPU周期长度cpu_shares(int) ---- CPU占有率(相对权重)cpuset_cpus(str) ---- 允许执行的CPUs (0-3, 0, 1)detach(bool) ---- 在后台运行容器并返回一个 Container 对象devices(list) ---- 将主机设备作为以下形式的字符串列表公开给容器:<path_on_host>:<path_in_container>:<cgroup_permissions>device_requests(list) ---- 将主机资源(如GPU)公开给容器,作为 docker.types.DeviceRequest 实例dns(list) ---- 设置自定义的DNS服务器dns_opt(list) ---- 要添加到容器的 resolv.conf 文件dns_search(list) ---- 域名系统搜索域domainname(str or list) ---- 设置自定义DNS搜索域entrypoint(str or list) ---- 容器的入口点environment(dict or list) ---- 要在容器内设置的环境变量,格式为字典或字符串列表 ["PYTHONPATH=xxx"]extra_hosts(dict) ---- 要在容器内解析的其他主机名,作为主机名到IP地址的映射group_add(list) ---- 容器进程将以其身份运行的其他组名或ID的列表healthcheck(dict) ---- 指定要执行的测试以检查容器是否正常hostname(str) ---- 容器的可选主机名isolation(str) ---- 使用隔离技术,默认为 Nonekernel_memory(int or str) ---- 内核内存限制labels(dict or list) ---- 以字典或者列表(空值)的形式,例如 {"label1": "value1", "label2": "value2"} 或 ["label1", "label2"]links(dict) ---- 链接的映射使用 {'container': 'alias'} 格式化,别名是可选的log_config(LogConfig) ---- 日志记录配置mac_address(str) ---- 要分配给容器的MAC地mem_limit(int or str) ---- 内存限制name(str) ---- 给容器起的名称network(str) ---- 此容器在创建时将连接到的网络的名称network_disabled(bool) ---- 禁用网络network_mode(str) ---- 以下其中一项: 桥接模式bridge、主机模式host、none、container:<name|id>ports(dict) ---- 要绑定到容器内部的端口,字典形式:{'2222/tcp': 3333} 会将容器内的端口2222暴露为主机上的端口3333privileged(bool) ---- 将扩展权限授予此容器read_only(bool) ---- 将容器的根文件系统挂载为只读remove(bool) ---- 当容器运行完毕后,将其移除。默认为 Falserestart_policy(dict) ---- 容器退出时重新启动,配置为带有关键字的词典:Name取值只能是 on-failure 或 always ,MaximumRetryCount 为失败时重新启动容器的次数。例如: {"Name": "on-failure", "MaximumRetryCount": 5}shm_size(str or int) ---- /dev/shm的大小,比如1Gstdin_open(bool) ---- 保持 STDIN 打开,即使没有连接stdout(bool) ---- 当detach=False时日志从STDOUT 返回 ,默认为 Truestderr(bool) ---- 当detach=False时日志从STDERR 返回 ,默认为 Falsestream(bool) ---- 如果设置为True,且 detach 为 False,则返回日志生成器而不是字符串,如果detach 为True将忽略。默认为 Falsesysctls(dict) ---- 要在容器中设置的内核参数tmpfs(dict) ---- 要挂载的临时文件系统,作为将容器内的路径映射到该路径的选项的字典。例如:{'/mnt/vol2': '', '/mnt/vol1': 'size=3G,uid=1000'}tty(bool) ---- 分配一个伪TTYuser(str or int) ---- 在容器内运行命令的用户名或UIDversion(str) ---- 要使用的API的版本。设为 auto 自动检测服务器的版本。默认为1.35volume_driver(str) ---- 卷驱动程序/插件的名称volumes(dict or list) ---- 用于配置装载在容器内的卷的字典。键是主机路径或卷名,值是包含键的字典,比如:{'/home/user1/': {'bind': '/mnt/vol2', 'mode': 'rw'},'/var/www': {'bind': '/mnt/vol1', 'mode': 'ro'}},其中bind表示在容器内挂载卷的路径,mode要么为rw 以读/写方式装载卷,或 ro 以只读方式装载它。也可以是列表形式直接映射:['/home/user1/:/mnt/vol2','/var/www:/mnt/vol1']working_dir(str) ---- 容器的工作目录的路径上述的参数并没有完全列举完,只对可能用到的进行了介绍,下面看下具体如何使用:
container = client.containers.run(image='ubuntu:latest',
command='/bin/bash',
user='root',
name='docker_test',
volumes=['/home/liyanpeng/docker-test:/home/liyanpeng/docker-test'],
working_dir='/home/liyanpeng',
tty=True,
detach=True,
stdin_open=True,
environment=['PYTHONPATH=xxxxx:$PYTHONPATH'])
# 如果detach=True,那么在容器内的输出信息需要通过container.logs()来查看
# 如果detach=False,可以直接print(container)来查看信息
Container对象是容器对象的本地表示形式,其主要有以下方法:
| 属性 | 功能 | 备注 |
|---|---|---|
attrs | 容器的属性信息 | 无 |
id | 容器的id | 无 |
image | 容器的容器的图像 | 无 |
labels | 作为词典的容器的标签 | 无 |
name | 容器的名称 | 无 |
short_id | 对象的ID,截断为12个字符 | 无 |
status | 容器的状态,例如running 或 exited | 无 |
attach(**kwargs) | 附在这个容器上 | 无 |
commit(repository=None, tag=None, **kwargs) | 将容器提交到映像 | docker commit |
diff() | 检查容器的文件系统上的更改 | 无 |
exec_run(cmd) | 在该容器内运行命令 | docker exec |
export(chunk_size=2097152) | 将容器的文件系统的内容导出为TAR压缩包 | 无 |
logs(**kwargs) | logs(**kwargs) | docker logs |
remove(**kwargs) | 移除这个容器 | docker rm |
rename(name) | 重命名此容器 | docker rename |
restart(**kwargs) | 重新启动此容器 | docker restart |
start(**kwargs) | 启动这个容器 | docker start |
stats(**kwargs) | 此容器的流统计信 | docker stats |
stop(**kwargs) | 停止容器 | docker stop |
top(**kwargs) | 显示容器正在运行的进程 | 无 |
update(**kwargs) | 更新容器的资源配置 | 无 |
wait(**kwargs) | 等容器停止,然后返回其退出代码 | docker wait |
# -*- coding:utf-8 -*-
# Author: liyanpeng
# Email: youran.xia@foxmail.com
# Datetime: 2023/2/3 17:16
# Filename: python_docker·py
import docker
from packaging.version import Version
class PythonDocker(object):
image_file = '/home/liyanpeng/ubuntu-20.04.tar.gz'
repository = 'ubuntu'
tag = 'latest'
localhost_dir = '/home/liyanpeng/docker-test'
container_dir = '/home/liyanpeng/docker-test'
container = None
container_name = 'python_docker'
client = docker.from_env()
# client = docker.Dockerclient("ssh://username@yourip", use_ssh_client=True)
@classmethod
def load_image(cls):
with open(cls.image_file, 'rb') as f:
img = cls.client.images.load(f)
img_obj = img[0]
print('Image Info: ', img_obj.short_id, img_obj.tags)
@classmethod
def check_version(cls):
docker_version = cls.client.version()['Components'][0]['Version']
assert Version(docker_version) >= Version('19.03'), 'Docker version requires: docker >= 19.03.'
@classmethod
def run_container(cls):
try:
cls.container = cls.client.containers.run('{}:{}'.format(cls.repository, cls.tag),
command='/bin/bash',
user='root',
name=cls.container_name,
volumes=['{}:{}'.format(cls.localhost_dir, cls.container_dir)],
working_dir='/home',
tty=True,
detach=True,
stdin_open=True,
environment=['PYTHONPATH=xxxxx:$PYTHONPATH'])
except Exception as err:
cls.container = cls.client.containers.get(cls.container_name)
@classmethod
def run_docker(cls):
result = cls.container.exec_run('python3 x.py') # 在容器内执行代码
print(result.exit_code, result.output.decode('utf-8'))
@classmethod
def close_docker(cls):
cls.container.stop() # 停止容器 ==> docker stop id
cls.container.remove() # 删除容器 ==> docker rm id
cls.client.close() # 关闭连接
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po