AI MLOps学习:用Docker Compose跑通模型监控最小闭环
MLOps 学习最容易走偏的地方,是一上来就研究平台选型。
对零基础用户来说,先跑通一个能验证的最小闭环更有价值:启动一个推理服务,让它暴露调用次数和延迟指标,再用 Prometheus 采集、Grafana 展示。
本文就在一台 Linux 服务器上用 Docker Compose 完成这件事,全程不需要 GPU 和真实大模型。
先确认服务器和目录条件
这套流程适合已经能 SSH 登录 Linux 服务器、装好 Docker 和 Docker Compose 的环境。
如果还没装 Docker,先按系统官方文档完成安装,并确认下面两条命令都有输出:
docker --version
docker compose version
接着创建工作目录,后续所有文件都放在这个目录下,避免路径混乱:
mkdir -p ~/mlops-demo && cd ~/mlops-demo
本文用 Python 标准库写一个极简推理接口,不依赖模型文件。
它只模拟推理耗时并记录请求指标,目的是让你把监控链路跑通,而不是评估模型效果。
写推理服务并暴露指标
在 ~/mlops-demo 下新建 app.py,内容如下:
import time
import random
from http.server import BaseHTTPRequestHandler, HTTPServer
from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST
REQUESTS = Counter('inference_requests_total', 'Total inference requests')
LATENCY = Histogram('inference_latency_seconds', 'Inference latency')
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/metrics':
data = generate_latest()
self.send_response(200)
self.send_header('Content-Type', CONTENT_TYPE_LATEST)
self.end_headers()
self.wfile.write(data)
return
if self.path == '/predict':
REQUESTS.inc()
start = time.time()
time.sleep(random.uniform(0.1, 0.4))
LATENCY.observe(time.time() - start)
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(b'{"result":"ok"}')
return
self.send_response(404)
self.end_headers()
HTTPServer(('0.0.0.0', 8000), Handler).serve_forever()
再新建 requirements.txt,固定依赖版本,避免不同机器安装结果不一致:
prometheus-client==0.20.0
用 Compose 串起采集和展示
在同一个目录新建 docker-compose.yml,把推理服务、Prometheus 和 Grafana 放到同一网络中:
services:
inference:
image: python:3.11-slim
working_dir: /app
volumes:
- ./app.py:/app/app.py
- ./requirements.txt:/app/requirements.txt
command: sh -c "pip install -r requirements.txt && python app.py"
ports:
- "8000:8000"
prometheus:
image: prom/prometheus:v2.53.0
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
depends_on:
- inference
grafana:
image: grafana/grafana:11.1.0
ports:
- "3000:3000"
depends_on:
- prometheus
新建 prometheus.yml,让 Prometheus 每 5 秒抓一次推理服务的指标:
scrape_configs:
- job_name: 'inference'
scrape_interval: 5s
static_configs:
- targets: ['inference:8000']
启动前先检查 Compose 文件语法:
docker compose config
没有报错再后台启动:
docker compose up -d
首次启动需要下载镜像和安装 Python 依赖,等待几十秒后执行 docker compose ps,三个服务状态应为 running 或 Up。
发一次请求并检查指标
先确认推理接口能响应:
curl http://127.0.0.1:8000/predict
预期返回 {"result":"ok"}。
再查看原始指标中是否出现请求计数:
curl -s http://127.0.0.1:8000/metrics | grep inference_requests_total
如果能看到类似 inference_requests_total 1.0 的行,说明服务端埋点正常。
接着打开 http://服务器IP:9090,在 Prometheus 查询框输入 inference_requests_total 并执行,应能查到数据。
最后访问 http://服务器IP:3000 登录 Grafana,默认账号密码均为 admin,首次登录会要求修改密码。
添加 Prometheus 数据源时地址填 http://prometheus:9090,保存后新建面板查询同一个指标即可看到曲线。
容易踩坑的地方
端口被占用:
如果 docker compose up -d 报端口冲突,
先用 ss -lntp 查看 8000、
9090、
3000 是否已被其他程序占用,
再修改 Compose 中左侧的宿主机端口。
Grafana 里查不到数据:先确认 Prometheus 的 Targets 页面中 inference 状态为 UP。
如果显示 DOWN,检查 prometheus.yml 中的目标地址是否写成 inference:8000,容器之间不能用 127.0.0.1 互访。
面板修改后重启丢失:本文没有为 Grafana 挂载数据卷,适合临时验证。
需要长期保留面板时,在 Grafana 服务下增加卷映射,例如 ./grafana-data:/var/lib/grafana,再重建容器。
只记录指标不记录日志:监控闭环通常还需要日志。
可以在 app.py 的 /predict 分支中增加一行标准输出打印,再用 docker compose logs -f inference 观察请求记录。
验证最小闭环是否成立
判断这套环境是否可用,不看容器是否启动,而看三件事是否同时成立:调用 /predict 后指标数值增加,Prometheus 能查询到该指标,Grafana 面板能画出随时间变化的曲线。
三项都通过,就说明你已经完成了一次可验证的 AI MLOps 学习练习。
后续再替换成真实模型服务、增加告警规则或接入日志系统,都是在这个闭环上逐步扩展。