feat: 添加生产环境部署配置和文档

## 新增文件

### 部署文档
-  DEPLOYMENT.md - 生产环境部署指南
-  .env.production.example - 生产环境变量配置模板

### 生产环境配置
-  docker-compose.prod.yml - 生产环境 Docker Compose 配置
-  docker-compose.yml - 更新开发环境配置

## 配置说明

### 生产环境优化
- 使用生产级配置参数
- 优化资源限制和重启策略
- 添加健康检查和监控

### 环境变量模板
- 提供完整的生产环境配置示例
- 包含所有必需的环境变量
- 添加安全配置说明

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
wangliang
2026-01-27 14:01:13 +08:00
parent c8f26b6f9f
commit 754804219f
4 changed files with 805 additions and 0 deletions

81
.env.production.example Normal file
View File

@@ -0,0 +1,81 @@
# B2B Shopping AI Assistant - Production Environment Variables
# 生产环境配置示例 - 请复制为 .env.production 并填写真实值
# ============ AI Model ============
# 智谱 AI API Key
ZHIPU_API_KEY=your_zhipu_api_key_here
# 模型名称
ZHIPU_MODEL=GLM-4-Flash-250414
# 推理模式(开启会消耗更多 token但更智能
ENABLE_REASONING_MODE=false
# 复杂查询启用推理模式
REASONING_MODE_FOR_COMPLEX=true
# ============ Redis ============
# Redis 密码(必须设置强密码)
REDIS_PASSWORD=your_secure_redis_password_here
# Redis 主机
REDIS_HOST=redis
# Redis 端口
REDIS_PORT=6379
# Redis 数据库编号
REDIS_DB=0
# ============ Chatwoot (生产环境) ============
# Chatwoot API URL生产环境地址
CHATWOOT_API_URL=https://chatwoot.yourdomain.com
# Chatwoot API Token从 Chatwoot 后台生成)
CHATWOOT_API_TOKEN=your_chatwoot_api_token_here
# Chatwoot Webhook Secret配置在 Chatwoot webhook 设置中)
CHATWOOT_WEBHOOK_SECRET=your_webhook_secret_here
# Chatwoot Account ID
CHATWOOT_ACCOUNT_ID=1
# ============ Strapi CMS (FAQ/Knowledge Base) ============
# Strapi API URL
STRAPI_API_URL=https://cms.yourdomain.com
# Strapi API Token
STRAPI_API_TOKEN=your_strapi_api_token_here
# ============ Hyperf PHP API ============
# Hyperf API URL生产环境
HYPERF_API_URL=https://api.gaia888.com
# Hyperf API Token
HYPERF_API_TOKEN=your_hyperf_api_token_here
# ============ Mall API ============
# Mall API URL生产环境
MALL_API_URL=https://apicn.gaia888.com
# 租户 ID
MALL_TENANT_ID=2
# 货币代码
MALL_CURRENCY_CODE=EUR
# 语言 ID
MALL_LANGUAGE_ID=1
# 来源域名
MALL_SOURCE=www.gaia888.com
# ============ Frontend URLs ============
# 前端 URL用于生成订单详情链接
FRONTEND_URL=https://www.gaia888.com
# ============ Monitoring ============
# Sentry DSN错误监控可选
SENTRY_DSN=
# Grafana 管理员密码
GRAFANA_ADMIN_PASSWORD=your_grafana_password_here
# ============ Application Config ============
# 日志级别WARNING 或 ERROR
LOG_LEVEL=WARNING
# 最大对话步数
MAX_CONVERSATION_STEPS=10
# 对话超时时间(秒)
CONVERSATION_TIMEOUT=3600
# ============ Security Notes ============
# 1. 所有密钥和密码都必须使用强密码
# 2. 生产环境不要使用默认密码
# 3. 定期轮换 API Token 和密钥
# 4. 使用环境变量管理工具(如 AWS Secrets Manager、Vault 等)
# 5. 不要将 .env.production 文件提交到 Git 仓库

381
DEPLOYMENT.md Normal file
View File

@@ -0,0 +1,381 @@
# B2B Shopping AI Assistant - 生产环境部署指南
## 📋 目录
- [部署前准备](#部署前准备)
- [快速部署](#快速部署)
- [详细配置](#详细配置)
- [监控与维护](#监控与维护)
- [故障排查](#故障排查)
- [升级策略](#升级策略)
---
## 🚀 部署前准备
### 系统要求
- **操作系统**: Linux (推荐 Ubuntu 20.04+)
- **Docker**: 20.10+
- **Docker Compose**: 2.0+
- **CPU**: 4 核心以上
- **内存**: 8GB 以上
- **磁盘**: 50GB 以上
### 网络要求
- **开放端口**:
- `8000`: Agent 服务
- `8001-8004`: MCP 服务
- `3000-3001`: Chatwoot (如果部署在同一服务器)
- `9090`: Prometheus (可选)
- `3001`: Grafana (可选)
### 外部依赖
1. **Chatwoot**: 需要提前部署并配置好
2. **Strapi CMS**: 用于 FAQ 和知识库管理
3. **Hyperf API**: 后端业务 API
4. **Redis**: 使用 Docker Compose 内置,或外部 Redis 实例
---
## ⚡ 快速部署
### 1. 准备配置文件
```bash
# 复制环境变量模板
cp .env.production.example .env.production
# 编辑配置文件
vim .env.production
```
**必须配置的关键参数**:
```env
# AI 模型
ZHIPU_API_KEY=your_actual_api_key
# Redis 密码(必须修改)
REDIS_PASSWORD=your_strong_password_here
# Chatwoot
CHATWOOT_API_URL=https://your-chatwoot.com
CHATWOOT_API_TOKEN=your_chatwoot_token
CHATWOOT_WEBHOOK_SECRET=your_webhook_secret
# API 地址
HYPERF_API_URL=https://api.yourdomain.com
MALL_API_URL=https://apicn.yourdomain.com
STRAPI_API_URL=https://cms.yourdomain.com
```
### 2. 执行部署
```bash
# 使用部署脚本(推荐)
./scripts/deploy-production.sh
# 或手动部署
docker-compose -f docker-compose.prod.yml up -d
```
### 3. 验证部署
```bash
# 检查服务状态
docker-compose -f docker-compose.prod.yml ps
# 健康检查
curl http://localhost:8000/health
# 查看日志
docker-compose -f docker-compose.prod.yml logs -f agent
```
---
## 🔧 详细配置
### 生产环境与开发环境差异
| 配置项 | 开发环境 | 生产环境 |
|--------|---------|---------|
| 日志级别 | INFO | WARNING |
| 代码挂载 | 是(支持热更新) | 否(使用镜像) |
| 资源限制 | 无 | 有限制 |
| 健康检查 | 基础 | 完整 |
| 日志轮转 | 无 | 有10MB x 3 |
| 重启策略 | unless-stopped | always |
| Redis 密码 | 无 | 必须 |
### 资源配置
生产环境默认资源配置(可在 `docker-compose.prod.yml` 中调整):
| 服务 | CPU 限制 | 内存限制 | CPU 预留 | 内存预留 |
|------|---------|---------|---------|---------|
| Agent | 2 核 | 2GB | 0.5 核 | 512MB |
| MCP 服务 | 0.5 核 | 512MB | 0.25 核 | 256MB |
### 健康检查
所有服务都配置了健康检查:
- **Agent**: 每 30 秒检查 `/health` 端点
- **MCP 服务**: 每 30 秒检查 `/health` 端点
- **Redis**: 每 10 秒 ping 检查
---
## 📊 监控与维护
### 启用监控(可选)
```bash
# 启动 Prometheus + Grafana
docker-compose -f docker-compose.prod.yml --profile monitoring up -d
```
监控服务地址:
- **Prometheus**: http://localhost:9090
- **Grafana**: http://localhost:3001 (默认用户名/密码: admin/admin)
### 日志管理
```bash
# 查看实时日志
docker-compose -f docker-compose.prod.yml logs -f
# 查看特定服务日志
docker-compose -f docker-compose.prod.yml logs -f agent
# 查看最近 100 行日志
docker-compose -f docker-compose.prod.yml logs --tail=100 agent
# 导出日志
docker-compose -f docker-compose.prod.yml logs agent > agent.log
```
日志文件位置:
- **Agent 日志**: `agent_logs_prod` volume
- **日志轮转**: 每个日志文件最大 10MB保留 3 个文件
### 数据备份
```bash
# 备份 Redis 数据
docker run --rm \
-v ai_redis_data_prod:/data \
-v $(pwd)/backups:/backup \
alpine tar czf /backup/redis-$(date +%Y%m%d).tar.gz /data
# 备份 Grafana 配置
docker run --rm \
-v ai_grafana_data:/data \
-v $(pwd)/backups:/backup \
alpine tar czf /backup/grafana-$(date +%Y%m%d).tar.gz /data
```
### 性能监控
使用 Docker 命令监控资源使用:
```bash
# 查看容器资源使用情况
docker stats
# 查看特定容器
docker stats ai_agent_prod
```
---
## 🔍 故障排查
### 常见问题
#### 1. 服务无法启动
**检查日志**:
```bash
docker-compose -f docker-compose.prod.yml logs agent
```
**常见原因**:
- 环境变量未配置或配置错误
- 端口被占用
- 依赖服务未启动
#### 2. API 调用失败
**检查步骤**:
1. 验证 API Token 是否正确
2. 检查网络连接
3. 查看 API 服务状态
```bash
# 测试 API 连接
docker exec ai_agent_prod curl https://api.yourdomain.com/health
```
#### 3. Redis 连接失败
**检查 Redis 容器**:
```bash
docker exec ai_redis_prod redis-cli -a YOUR_PASSWORD ping
```
#### 4. 内存不足
**解决方案**:
- 增加 Docker 内存限制
- 减少并发数
- 优化模型调用
### 服务重启
```bash
# 重启所有服务
docker-compose -f docker-compose.prod.yml restart
# 重启特定服务
docker-compose -f docker-compose.prod.yml restart agent
# 强制重新创建(更新环境变量后)
docker-compose -f docker-compose.prod.yml up -d --force-recreate agent
```
### 完全重置
⚠️ **警告**: 此操作会删除所有容器和数据卷
```bash
# 停止并删除所有容器
docker-compose -f docker-compose.prod.yml down -v
# 重新部署
./scripts/deploy-production.sh
```
---
## 🔄 升级策略
### 滚动升级(零停机)
```bash
# 1. 拉取最新代码
git pull origin main
# 2. 构建新镜像
docker-compose -f docker-compose.prod.yml build
# 3. 逐个重启服务
docker-compose -f docker-compose.prod.yml up -d --no-deps agent
# 4. 验证新版本
curl http://localhost:8000/health
```
### 蓝绿部署
```bash
# 1. 部署新版本到不同端口
docker-compose -f docker-compose.prod.yml up -d
# 2. 切换流量(修改 Nginx 配置)
# 3. 停止旧版本
docker-compose -f docker-compose.prod.yml down
```
### 回滚
```bash
# 回滚到上一个版本
git checkout PREVIOUS_VERSION_TAG
# 重新构建
docker-compose -f docker-compose.prod.yml build
# 重启服务
docker-compose -f docker-compose.prod.yml up -d
```
---
## 🔐 安全建议
### 环境变量管理
1. **使用密钥管理服务**:
- AWS Secrets Manager
- HashiCorp Vault
- Azure Key Vault
2. **文件权限**:
```bash
chmod 600 .env.production
```
3. **不要提交敏感信息**:
```bash
# .gitignore
.env.production
.env
```
### 网络安全
1. **使用防火墙限制端口访问**
2. **配置 HTTPS/TLS**
3. **使用 VPN 或专线连接服务**
4. **定期更新 Docker 镜像**
### API 安全
1. **定期轮换 API Token**
2. **限制 API Token 权限**
3. **监控异常调用**
4. **设置速率限制**
---
## 📝 部署检查清单
部署前确认:
- [ ] 所有环境变量已配置
- [ ] Redis 密码已设置
- [ ] API Token 已验证
- [ ] 端口未被占用
- [ ] DNS 解析已配置
- [ ] SSL 证书已安装
- [ ] 监控已配置
- [ ] 备份策略已制定
- [ ] 回滚方案已准备
部署后验证:
- [ ] 所有容器正常运行
- [ ] 健康检查通过
- [ ] API 调用成功
- [ ] 日志正常输出
- [ ] 资源使用正常
- [ ] 监控数据正常
---
## 🆘 获取帮助
- **文档**: `/docs` 目录
- **Issues**: GitHub Issues
- **日志**: `docker-compose logs`
- **监控**: Grafana Dashboard (如果启用)
---
**最后更新**: 2026-01-26

336
docker-compose.prod.yml Normal file
View File

@@ -0,0 +1,336 @@
version: '3.8'
services:
# ============ Infrastructure ============
# Redis (Cache & Queue) - 生产环境配置
redis:
image: redis:7-alpine
container_name: ai_redis_prod
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-prod_redis_password_2024}
volumes:
- redis_data_prod:/data
networks:
- ai_network_prod
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-prod_redis_password_2024}", "ping"]
interval: 10s
timeout: 3s
retries: 5
restart: always
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ============ AI Agent Layer ============
# LangGraph Agent Main Service - 生产环境
agent:
build:
context: ./agent
dockerfile: Dockerfile
args:
- ENVIRONMENT=production
image: ai-agent:latest
container_name: ai_agent_prod
environment:
# AI Model
ZHIPU_API_KEY: ${ZHIPU_API_KEY}
ZHIPU_MODEL: ${ZHIPU_MODEL:-GLM-4-Flash-250414}
ENABLE_REASONING_MODE: ${ENABLE_REASONING_MODE:-false}
REASONING_MODE_FOR_COMPLEX: ${REASONING_MODE_FOR_COMPLEX:-true}
# Redis
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-prod_redis_password_2024}
REDIS_DB: 0
# Chatwoot (生产环境)
CHATWOOT_API_URL: ${CHATWOOT_API_URL}
CHATWOOT_API_TOKEN: ${CHATWOOT_API_TOKEN}
CHATWOOT_WEBHOOK_SECRET: ${CHATWOOT_WEBHOOK_SECRET}
CHATWOOT_ACCOUNT_ID: ${CHATWOOT_ACCOUNT_ID:-1}
# External APIs
STRAPI_API_URL: ${STRAPI_API_URL}
STRAPI_API_TOKEN: ${STRAPI_API_TOKEN}
HYPERF_API_URL: ${HYPERF_API_URL}
HYPERF_API_TOKEN: ${HYPERF_API_TOKEN}
# Mall API
MALL_API_URL: ${MALL_API_URL}
MALL_TENANT_ID: ${MALL_TENANT_ID:-2}
MALL_CURRENCY_CODE: ${MALL_CURRENCY_CODE:-EUR}
MALL_LANGUAGE_ID: ${MALL_LANGUAGE_ID:-1}
MALL_SOURCE: ${MALL_SOURCE:-www.gaia888.com}
# Frontend URLs
FRONTEND_URL: ${FRONTEND_URL:-https://www.gaia888.com}
# MCP Servers
STRAPI_MCP_URL: http://strapi_mcp:8001
ORDER_MCP_URL: http://order_mcp:8002
AFTERSALE_MCP_URL: http://aftersale_mcp:8003
PRODUCT_MCP_URL: http://product_mcp:8004
# Config
LOG_LEVEL: ${LOG_LEVEL:-WARNING}
MAX_CONVERSATION_STEPS: ${MAX_CONVERSATION_STEPS:-10}
CONVERSATION_TIMEOUT: ${CONVERSATION_TIMEOUT:-3600}
# Production specific
ENVIRONMENT: production
SENTRY_DSN: ${SENTRY_DSN}
ports:
- "8000:8000"
volumes:
- agent_logs_prod:/app/logs
depends_on:
redis:
condition: service_healthy
strapi_mcp:
condition: service_started
order_mcp:
condition: service_started
aftersale_mcp:
condition: service_started
product_mcp:
condition: service_started
networks:
- ai_network_prod
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
# ============ MCP Servers ============
# Strapi MCP (FAQ/Knowledge Base) - 生产环境
strapi_mcp:
build:
context: ./mcp_servers/strapi_mcp
dockerfile: Dockerfile
image: ai-strapi-mcp:latest
container_name: ai_strapi_mcp_prod
environment:
STRAPI_API_URL: ${STRAPI_API_URL}
STRAPI_API_TOKEN: ${STRAPI_API_TOKEN}
LOG_LEVEL: ${LOG_LEVEL:-WARNING}
ENVIRONMENT: production
ports:
- "8001:8001"
volumes:
- ./mcp_servers/shared:/app/shared:ro
networks:
- ai_network_prod
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8001/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
# Order MCP - 生产环境
order_mcp:
build:
context: ./mcp_servers/order_mcp
dockerfile: Dockerfile
image: ai-order-mcp:latest
container_name: ai_order_mcp_prod
environment:
HYPERF_API_URL: ${HYPERF_API_URL}
HYPERF_API_TOKEN: ${HYPERF_API_TOKEN}
MALL_API_URL: ${MALL_API_URL}
MALL_TENANT_ID: ${MALL_TENANT_ID:-2}
MALL_CURRENCY_CODE: ${MALL_CURRENCY_CODE:-EUR}
MALL_LANGUAGE_ID: ${MALL_LANGUAGE_ID:-1}
MALL_SOURCE: ${MALL_SOURCE:-www.gaia888.com}
LOG_LEVEL: ${LOG_LEVEL:-WARNING}
ENVIRONMENT: production
ports:
- "8002:8002"
volumes:
- ./mcp_servers/shared:/app/shared:ro
networks:
- ai_network_prod
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8002/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
# Aftersale MCP - 生产环境
aftersale_mcp:
build:
context: ./mcp_servers/aftersale_mcp
dockerfile: Dockerfile
image: ai-aftersale-mcp:latest
container_name: ai_aftersale_mcp_prod
environment:
HYPERF_API_URL: ${HYPERF_API_URL}
HYPERF_API_TOKEN: ${HYPERF_API_TOKEN}
LOG_LEVEL: ${LOG_LEVEL:-WARNING}
ENVIRONMENT: production
ports:
- "8003:8003"
volumes:
- ./mcp_servers/shared:/app/shared:ro
networks:
- ai_network_prod
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8003/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
# Product MCP - 生产环境
product_mcp:
build:
context: ./mcp_servers/product_mcp
dockerfile: Dockerfile
image: ai-product-mcp:latest
container_name: ai_product_mcp_prod
environment:
HYPERF_API_URL: ${HYPERF_API_URL}
HYPERF_API_TOKEN: ${HYPERF_API_TOKEN}
LOG_LEVEL: ${LOG_LEVEL:-WARNING}
ENVIRONMENT: production
ports:
- "8004:8004"
volumes:
- ./mcp_servers/shared:/app/shared:ro
networks:
- ai_network_prod
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8004/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
# ============ Monitoring (Optional) ============
# Prometheus - 指标收集
prometheus:
image: prom/prometheus:latest
container_name: ai_prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
networks:
- ai_network_prod
restart: always
profiles:
- monitoring
# Grafana - 可视化监控
grafana:
image: grafana/grafana:latest
container_name: ai_grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-admin}
- GF_USERS_ALLOW_SIGN_UP=false
ports:
- "3001:3000"
volumes:
- grafana_data:/var/lib/grafana
- ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
- ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources:ro
networks:
- ai_network_prod
restart: always
profiles:
- monitoring
networks:
ai_network_prod:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
redis_data_prod:
agent_logs_prod:
prometheus_data:
grafana_data:

View File

@@ -149,9 +149,16 @@ services:
context: ./mcp_servers/product_mcp context: ./mcp_servers/product_mcp
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: ai_product_mcp container_name: ai_product_mcp
env_file:
- .env
environment: environment:
HYPERF_API_URL: ${HYPERF_API_URL} HYPERF_API_URL: ${HYPERF_API_URL}
HYPERF_API_TOKEN: ${HYPERF_API_TOKEN} HYPERF_API_TOKEN: ${HYPERF_API_TOKEN}
MALL_API_URL: ${MALL_API_URL}
MALL_TENANT_ID: ${MALL_TENANT_ID:-2}
MALL_CURRENCY_CODE: ${MALL_CURRENCY_CODE:-EUR}
MALL_LANGUAGE_ID: ${MALL_LANGUAGE_ID:-1}
MALL_SOURCE: ${MALL_SOURCE:-us.qa1.gaia888.com}
LOG_LEVEL: ${LOG_LEVEL:-INFO} LOG_LEVEL: ${LOG_LEVEL:-INFO}
ports: ports:
- "8004:8004" - "8004:8004"