Python 获取 Docker 容器实时资源占用(CPU、内存、IO等)多种实现方式详解

Python 获取 Docker 容器实时资源占用(CPU、内存、IO等)多种实现方式详解

在运维监控、容器管理平台、云桌面系统等场景中,我们经常需要实时获取 Docker 容器的 CPU、内存、网络、磁盘 IO 等资源使用情况。本文总结了 5 种常用的 Python 实现方式,从最基础到生产可用的方案逐步讲解,帮助你根据实际需求选择最合适的写法。


一、使用 docker stats --no-stream 最简版(适合快速查看)

python 复制代码
# -*- encoding: utf-8 -*-
from subprocess import Popen, PIPE, STDOUT

def Run_Cmd(cmd):
    p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
    stdout, _ = p.communicate()
    return p.returncode, stdout.strip().decode()

if __name__ == "__main__":
    cmd = 'docker stats --no-stream'        # 获取所有容器
    # cmd = 'docker stats 92d1f89c5bb4 --no-stream'  # 指定容器
    code, out = Run_Cmd(cmd)
    print(out)

输出示例:

复制代码
CONTAINER ID   NAME             CPU %     MEM USAGE / LIMIT     MEM %     NET I/O         BLOCK I/O       PIDS
7d0d088b44e6   centos7-novnc2   0.02%     144.2MiB / 7.774GiB   1.81%     2.44kB / 0B     249MB / 403MB   99

优点:简单直接

缺点:输出是人类可读的表格,不利于程序解析


二、使用 --format 自定义输出 + 结构化解析(推荐)

python 复制代码
# -*- encoding: utf-8 -*-
from subprocess import Popen, PIPE, STDOUT

def Run_Cmd(cmd):
    p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
    stdout, _ = p.communicate()
    return stdout.strip()

if __name__ == "__main__":
    cmd = ('docker stats --no-stream --format '
           '"{{.BlockIO}}#{{.CPUPerc}}#{{.Container}}#{{.ID}}#'
           '{{.MemPerc}}#{{.MemUsage}}#{{.Name}}#{{.NetIO}}#{{.PIDs}}##"')

    result = Run_Cmd(cmd).decode("utf-8")
    container_list = []

    for line in result.split("##"):
        if not line:
            continue
        fields = line.split("#")
        info = {
            'BlockIO':   fields[0],
            'CPUPerc':   fields[1],
            'Container': fields[2],
            'ID':        fields[3],
            'MemPerc':   fields[4],
            'MemUsage':  fields[5],
            'Name':      fields[6],
            'NetIO':     fields[7],
            'PIDs':      fields[8]
        }
        container_list.append(info)

    print(container_list)

输出:

python 复制代码
[{'BlockIO': '249MB / 403MB', 'CPUPerc': '0.02%', 'Container': 'centos7-novnc2', ...}]

优点:结构化数据、易于转为 JSON、前后端交互友好


三、使用 subprocess 列表方式(更安全,避免 shell 注入)

python 复制代码
from subprocess import Popen, PIPE
import json

try:
    shell = [
        'docker', 'stats', 'centos7-novnc2', '--no-stream', '--format',
        '{{.BlockIO}}#{{.CPUPerc}}#{{.Container}}#{{.ID}}#'
        '{{.MemPerc}}#{{.MemUsage}}#{{.Name}}#{{.NetIO}}#{{.PIDs}}'
    ]
    
    p = Popen(shell, stdout=PIPE, stderr=PIPE)
    response = {"code": 200, "msg": "success", "data": []}
    
    for line in p.stdout.readlines():
        line = line.decode("utf-8").strip()
        if not line:
            continue
        ls = line.split("#")
        info = {
            'BlockIO':   ls[0], 'CPUPerc': ls[1], 'Container': ls[2],
            'ID':        ls[3], 'MemPerc': ls[4],  'MemUsage': ls[5],
            'Name':      ls[6], 'NetIO':   ls[7],  'PIDs':    ls[8].strip()
        }
        response["data"].append(info)

except FileNotFoundError:
    response = {"code": 500, "msg": "docker 未安装"}

print(json.dumps(response, ensure_ascii=False, indent=2))

推荐用于 Web 接口返回 JSON 数据


四、自动生成 --format 模板的小工具(偷懒神器)

python 复制代码
p = {"BlockIO":"249MB / 403MB","CPUPerc":"0.02%","Container":"centos7-novnc2",
     "ID":"7d0d088b44e6","MemPerc":"1.81%","MemUsage":"144.2MiB / 7.774GiB",
     "Name":"centos7-novnc2","NetIO":"2.44kB / 0B","PIDs":"99"}

pd = []
for i, k in enumerate(p.keys()):
    pd.append(f"{{{{.{k}}}}}#")
    print(f"p.update({{'{k}': ls[{i}]}})")
print("\n生成的 format 字符串:")
print("".join(pd))

运行后自动输出:

bash 复制代码
docker stats --no-stream --format "{{.BlockIO}}#{{.CPUPerc}}#{{.Container}}#..."

以后想加新字段,直接改字典再运行即可


五、持续监控 + 计算平均内存使用率(适合压测报告)

python 复制代码
# -*- encoding: utf-8 -*-
from subprocess import Popen, PIPE, STDOUT
import time

def get_mem_usage(container_name):
    cmd = f'docker stats {container_name} --no-stream'
    p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT)
    output = p.stdout.read().decode("utf-8")
    lines = output.strip().split("\n")
    if len(lines) < 2:
        return 0.0
    # 第2行是数据,MemPerc 在第5列(索引4)
    mem_perc = lines[1].split()[4]  # 例如: 1.81%
    return float(mem_perc.rstrip("%"))

if __name__ == "__main__":
    container = "centos7-novnc2"
    total = 0.0
    count = 120

    print("开始监控容器内存使用率(每3秒采样一次,共120次)\n")
    for i in range(1, count + 1):
        mem = get_mem_usage(container)
        total += mem
        avg = total / i
        print(f"第{i:3d}次 | 当前: {mem:5.2f}% | 累计平均: {avg:.2f}%")
        time.sleep(3)

    print(f"\n120次采样平均内存使用率:{total/count:.2f}%")

适用于:

  • 压测前后资源占用对比
  • 自动化报告生成
  • 容器资源预警

总结对比

方式 是否结构化 是否安全 是否适合生产 推荐场景
直接 shell=True 输出表格 一般 调试用 快速查看
--format + split("#") 推荐 强烈推荐 前后端、监控系统
subprocess 列表传参 生产首选 Web API 接口
自动生成模板脚本 - - 开发辅助 快速扩展字段
循环采样统计平均值 推荐 压测/报告 性能测试分析

希望这篇文章能帮你在实际项目中快速实现 Docker 容器资源监控功能!喜欢记得点赞 + 收藏 ~

相关推荐
_一路向北_8 小时前
爬虫框架:Feapder使用心得
爬虫·python
皇族崛起8 小时前
【3D标注】- Unreal Engine 5.7 与 Python 交互基础
python·3d·ue5
你想知道什么?8 小时前
Python基础篇(上) 学习笔记
笔记·python·学习
Swizard9 小时前
速度与激情:Android Python + CameraX 零拷贝实时推理指南
android·python·ai·移动开发
一直跑9 小时前
Liunx服务器centos7离线升级内核(Liunx服务器centos7.9离线/升级系统内核)
python
leocoder9 小时前
大模型基础概念入门 + 代码实战(实现一个多轮会话机器人)
前端·人工智能·python
Buxxxxxx9 小时前
DAY 37 深入理解SHAP图
python
ada7_9 小时前
LeetCode(python)108.将有序数组转换为二叉搜索树
数据结构·python·算法·leetcode
请一直在路上9 小时前
python文件打包成exe(虚拟环境打包,减少体积)
开发语言·python
浩瀚地学9 小时前
【Arcpy】入门学习笔记(五)-矢量数据
经验分享·笔记·python·arcgis·arcpy