python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python获取Docker容器资源占用

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

作者:weixin_46244623

在运维监控、容器管理平台、云桌面系统等场景中,我们经常需要实时获取 Docker 容器的资源使用情况,本文总结了5种常用的实现方式,有需要的可以了解下

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

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

# -*- 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自定义输出 + 结构化解析(推荐)

# -*- 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)

输出:

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

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

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

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模板的小工具(偷懒神器)

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))

运行后自动输出:

docker stats --no-stream --format "{{.BlockIO}}#{{.CPUPerc}}#{{.Container}}#..."

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

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

# -*- 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 接口
自动生成模板脚本--开发辅助快速扩展字段
循环采样统计平均值推荐压测/报告性能测试分析

到此这篇关于Python获取Docker容器实时资源占用(CPU、内存、IO等)5种实现方式的文章就介绍到这了,更多相关Python获取Docker容器资源占用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文