构建高可用多容器AI系统:从Docker Compose到监控与可视化完整实践
Snippet/摘要
本文详细讲解如何使用Docker Compose构建多容器AI系统,包括核心服务、监控Prometheus、日志收集Fluentd、可视化Grafana及Streamlit前端,并提供完整配置示例与故障排查方法。
目录
系统概览与设计目标
本系统基于多代理架构(Multi-Agent System),支持企业级AI任务处理与分析。核心目标包括:
-
多容器隔离部署:各服务通过独立容器运行,保证资源隔离和可扩展性。 -
高可用性与自恢复:通过Docker Compose restart: unless-stopped策略和健康检查,实现自动重启和容器健康监控。 -
集中监控和可视化:使用Prometheus抓取指标,Grafana提供实时可视化,支持性能分析和告警。 -
日志集中化管理:Fluentd收集各服务日志,统一存储与分析。 -
Web交互界面:通过Streamlit提供用户友好的交互前端,并通过Nginx反向代理统一访问。
Docker Compose整体架构
系统使用Docker Compose version: '3.8'进行服务编排,主要组成如下:
| 服务名称 | 镜像/构建 | 端口映射 | 功能 |
|---|---|---|---|
| multi-agent-system | 本地Dockerfile | 8000(API)、8501(Streamlit原本暴露) | 核心AI业务逻辑 |
| redis | redis:7-alpine | 6379 | 缓存与消息队列 |
| postgres | postgres:15-alpine | 5432 | 数据存储与管理 |
| prometheus | prom/prometheus:latest | 9090 | 监控数据抓取 |
| grafana | grafana/grafana:latest | 3000 | 指标可视化与仪表盘 |
| nginx | nginx:alpine | 80/443 | 统一HTTP/HTTPS访问与反向代理 |
| fluentd | fluent/fluentd:v1.16-debian-1 | 24224 | 日志收集 |
| streamlit | 本地Dockerfile | 8501 | 用户交互界面(Web UI) |
| jupyter | 本地Dockerfile.jupyter | 8888 | 开发与调试环境(可选,dev profile) |
网络通过 multi-agent-network 桥接,确保各容器可通过服务名称互相访问,IP段配置为 172.20.0.0/16。
核心服务部署
Multi-Agent System
功能概述:
-
启动多代理系统,初始化核心代理(Research Agent、Analysis Agent) -
客服系统初始化(Tech Support、Billing Support、General Support) -
消息总线(Message Bus)实现内部消息通信,支持3个工作线程 -
支持Workflow Engine和性能监控
Docker Compose配置:
multi-agent-system:
build:
context: .
dockerfile: Dockerfile
container_name: multi-agent-system
ports:
- "8000:8000"
environment:
- PYTHONPATH=/app
- REDIS_HOST=redis
- POSTGRES_HOST=postgres
- LANGSMITH_API_KEY=${LANGSMITH_API_KEY:-}
volumes:
- ./logs:/app/logs
- ./data:/app/data
depends_on:
- redis
- postgres
networks:
- multi-agent-network
restart: unless-stopped
healthcheck:
test: ["CMD", "python", "-c", "import requests; requests.get('http://localhost:8000/metrics')"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
经验总结:
-
健康检查应使用实际可访问的HTTP端点 /metrics,而非不存在的/health。 -
/metrics端口必须在Python中使用start_http_server(8000)明确启动,保证Prometheus可抓取。
Redis缓存
-
镜像: redis:7-alpine -
端口映射: 6379:6379 -
数据卷: redis_data -
健康检查: redis-cli ping
“
经验提示:Prometheus不能直接抓取原生Redis端口,需要额外部署
redis-exporter服务。
PostgreSQL数据库
-
镜像: postgres:15-alpine -
数据卷挂载初始化SQL: ./scripts/init_db.sql -
环境变量配置:数据库名、用户名、密码 -
健康检查: pg_isready -U postgres
“
Prometheus抓取PostgreSQL指标同样需要
postgres-exporter,不能直接抓5432端口。
监控与可视化
Prometheus配置
monitoring/prometheus.yml 示例:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: "multi-agent-system"
static_configs:
- targets: ["multi-agent-system:8000"]
- job_name: "redis"
static_configs:
- targets: ["multi-agent-redis:9121"]
- job_name: "postgres"
static_configs:
- targets: ["multi-agent-postgres:9187"]
- job_name: "grafana"
metrics_path: /metrics
static_configs:
- targets: ["multi-agent-grafana:3000"]
核心经验:
-
原有端口8501未运行Streamlit时应禁用抓取。 -
Redis、Postgres必须抓HTTP暴露端点(Exporter),否则Prometheus报EOF。 -
Grafana默认不暴露指标,需要启用 GF_METRICS_ENABLED=true。
Grafana配置
-
默认管理员密码设置为 admin -
仪表盘存放路径: ./monitoring/grafana/dashboards -
数据源配置路径: ./monitoring/grafana/datasources -
网络: multi-agent-network -
依赖:Prometheus服务
“
经验提示:保证Grafana抓取Prometheus数据前,Prometheus job必须为UP状态。
日志收集系统Fluentd
fluentd.conf 配置:
<source>
@type forward
port 24224
bind 0.0.0.0
</source>
<match **>
@type file
path /var/log/multi-agent
append true
</match>
-
Fluentd收集所有容器日志 -
容器挂载 /logs到宿主机,方便统一分析 -
端口: 24224TCP/UDP
前端展示与Streamlit服务
新增独立Streamlit服务,解决原主容器8501端口未监听问题:
streamlit:
build:
context: .
dockerfile: Dockerfile.streamlit
container_name: multi-agent-streamlit
ports:
- "8501:8501"
volumes:
- ./ui:/app
networks:
- multi-agent-network
restart: unless-stopped
关键点:
-
Streamlit监听 0.0.0.0:8501,保证外部访问。 -
Nginx反向代理 /streamlit/到streamlit:8501,统一入口。 -
避免在主应用容器占用8501端口,减少冲突。
“
经验提示:在Windows上,检查端口占用:
netstat -ano | findstr :8501
Nginx反向代理配置
完整示例 nginx/nginx.conf:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
upstream multi_agent_system {
server multi-agent-system:8000;
}
upstream streamlit_app {
server streamlit:8501;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://multi_agent_system;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /streamlit/ {
proxy_pass http://streamlit_app/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
注意:
-
原 unknown log format "main"错误是因为log_format配置缺失或写法错误,已修正。 -
/streamlit/代理单独Streamlit容器,避免空响应。
常见问题排查
-
空响应 ERR_EMPTY_RESPONSE
-
检查容器是否真正监听端口 -
检查Nginx upstream配置是否正确 -
检查容器网络互通:
docker exec -it multi-agent-nginx sh -c "apk add curl; curl -sI http://streamlit:8501"返回200/302表示网络可达。
-
-
Prometheus抓取失败
-
原因:抓取端口非HTTP或未启动 -
解决:使用Exporter(Redis、Postgres),确保 /metrics可访问
-
-
Streamlit未运行
-
确认服务已启动:
docker compose ps docker logs --tail=50 multi-agent-streamlit-
确认端口8501映射正确,监听地址为 0.0.0.0
-
FAQ
Q1: 为什么访问 localhost:8501 返回空白?
A1: 原主应用未监听8501端口,需通过独立Streamlit服务监听,并确保Nginx代理正确。
Q2: Redis和Postgres指标为何Prometheus抓不到?
A2: 原端口不是HTTP服务,Prometheus必须抓HTTP Exporter(Redis Exporter 9121、Postgres Exporter 9187)。
Q3: Nginx日志报 unknown log format "main"?
A3: 因log_format定义缺失或格式错误,已在 nginx.conf修复。
Q4: 如何验证Multi-Agent System健康?
A4: 使用 /metrics端点:
curl http://localhost:8000/metrics
返回Prometheus文本格式即健康。
总结与经验要点
-
服务隔离:每个容器功能单一,避免端口冲突和依赖耦合。 -
端口健康检查:Prometheus抓取端口必须监听HTTP服务。 -
日志统一管理:Fluentd收集所有服务日志,方便长期审计和监控。 -
前端与反向代理:Streamlit独立服务 + Nginx代理,统一访问入口。 -
容器网络配置:使用桥接网络,确保服务名解析正常。 -
重建镜像和缓存清理:出现端口或依赖错误时,执行
docker compose build --no-cache
docker compose up -d
通过以上部署和配置,系统可实现:
-
可靠的多代理AI服务运行 -
Prometheus统一监控核心指标 -
Grafana仪表盘实时可视化 -
Streamlit前端页面稳定访问 -
Fluentd集中日志收集与分析
“
该方案经过实际运行验证,确保容器间通信、端口暴露、监控抓取和Web访问均可正常运作。
