Browse Source

feat: docker打包

zhangwl 2 months ago
parent
commit
81bd658123
6 changed files with 238 additions and 4 deletions
  1. 7 0
      .env
  2. 130 0
      DOCKER_DEPLOY.md
  3. 45 0
      Dockerfile
  4. 2 2
      app/db/ai_config.py
  5. 6 2
      app/db/redis_client.py
  6. 48 0
      docker-compose.yml

+ 7 - 0
.env

@@ -16,3 +16,10 @@ ACCESS_TOKEN_EXPIRE_MINUTES=30
 # souyue MongoDB
 SOUYUE_MONGO_URI=mongodb://dds-2zeeb9d15a7a55541.mongodb.rds.aliyuncs.com:3717,dds-2zeeb9d15a7a55542.mongodb.rds.aliyuncs.com:3717
 ARK_LOGS_MONGO_URI=mongodb://arkapi:arkapi@dds-2zedd8d70bde6e541.mongodb.rds.aliyuncs.com:3717,dds-2zedd8d70bde6e542.mongodb.rds.aliyuncs.com:3717/arklogs
+
+# redis
+REDIS_HOST=r-2zeitjlg0gdypzb4v6.redis.rds.aliyuncs.com
+REDIS_PORT=6379
+# 应用配置
+LOG_LEVEL=info
+ENVIRONMENT=production

+ 130 - 0
DOCKER_DEPLOY.md

@@ -0,0 +1,130 @@
+# Docker 部署指南
+
+## 快速开始
+
+### 1. 启动服务
+
+```bash
+# 构建并启动所有服务
+docker-compose up -d
+
+# 查看日志
+docker-compose logs -f chat-ai-api
+```
+
+### 2. 验证服务
+
+- API 文档:http://localhost:8000/docs
+- MongoDB:localhost:27017
+- Redis:localhost:6379
+
+## 生产环境调整
+
+### CORS 配置
+
+编辑 `main.py` 中的 CORS 设置,指定具体的允许域名:
+
+```python
+app.add_middleware(
+    CORSMiddleware,
+    allow_origins=["https://yourdomain.com", "https://www.yourdomain.com"],
+    allow_credentials=True,
+    allow_methods=["GET", "POST", "PUT", "DELETE"],
+    allow_headers=["*"],
+)
+```
+
+### 日志级别
+
+生产环境建议使用 `warning` 或 `error`:
+
+```bash
+LOG_LEVEL=warning docker-compose up -d
+```
+
+### 数据库持久化
+
+数据已通过 Docker volumes 持久化:
+- MongoDB: `mongodb_data`
+- Redis: `redis_data`
+
+### 扩展副本
+
+如需多个 API 实例,编辑 `docker-compose.yml`:
+
+```yaml
+services:
+  chat-ai-api-1:
+    # ... 配置
+    ports:
+      - "8001:8000"
+
+  chat-ai-api-2:
+    # ... 配置
+    ports:
+      - "8002:8000"
+```
+
+然后使用 Nginx 进行负载均衡。
+
+## 常用命令
+
+```bash
+# 启动服务
+docker-compose up -d
+
+# 停止服务
+docker-compose down
+
+# 查看日志
+docker-compose logs -f chat-ai-api
+
+# 重启服务
+docker-compose restart chat-ai-api
+
+# 进入容器
+docker-compose exec chat-ai-api bash
+
+# 查看服务状态
+docker-compose ps
+
+# 清理所有数据(谨慎)
+docker-compose down -v
+```
+
+## 故障排查
+
+### 容器启动失败
+
+```bash
+# 查看详细日志
+docker-compose logs chat-ai-api
+
+# 检查环境变量
+docker-compose config
+```
+
+### 数据库连接失败
+
+确保 MongoDB 和 Redis 已启动:
+
+```bash
+docker-compose ps
+```
+
+### 端口被占用
+
+修改 `docker-compose.yml` 中的端口映射:
+
+```yaml
+ports:
+  - "8001:8000"  # 改为其他端口
+```
+
+## 安全建议
+
+1. **修改默认密码**:MongoDB 和 Redis 的默认密码需要修改
+2. **环境变量保护**:`.env` 文件不要提交到版本控制
+3. **CORS 限制**:生产环境指定具体的允许域名
+4. **SECRET_KEY**:使用强随机密钥(至少32字符)
+5. **日志级别**:生产环境降低日志级别以减少日志输出

+ 45 - 0
Dockerfile

@@ -0,0 +1,45 @@
+# 多阶段构建 - 第一阶段:依赖安装
+FROM python:3.10-slim as builder
+
+WORKDIR /build
+
+# 安装系统依赖(某些Python包需要编译)
+RUN apt-get update && apt-get install -y --no-install-recommends \
+    gcc \
+    && rm -rf /var/lib/apt/lists/*
+
+# 复制requirements并安装Python依赖
+COPY requirements.txt .
+RUN pip install --user --no-cache-dir -r requirements.txt
+
+# 第二阶段:运行时镜像
+FROM python:3.10-slim
+
+WORKDIR /app
+
+# 创建非root用户(安全最佳实践)
+RUN useradd -m -u 1000 appuser
+
+# 从builder阶段复制已安装的依赖
+COPY --from=builder /root/.local /home/appuser/.local
+
+# 复制应用代码
+COPY --chown=appuser:appuser . .
+
+# 设置环境变量
+ENV PATH=/home/appuser/.local/bin:$PATH \
+    PYTHONUNBUFFERED=1 \
+    PYTHONDONTWRITEBYTECODE=1
+
+# 切换到非root用户
+USER appuser
+
+# 暴露端口
+EXPOSE 8000
+
+# 健康检查
+HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
+    CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/docs')" || exit 1
+
+# 启动应用
+CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]

+ 2 - 2
app/db/ai_config.py

@@ -1,5 +1,5 @@
 from pymongo import MongoClient
-from bson import ObjectId
+
 from datetime import datetime
 from dotenv import load_dotenv
 import os
@@ -92,4 +92,4 @@ def get_all_configs() -> list:
         return [{"_id": str(doc["_id"]), **{k: v for k, v in doc.items() if k != "_id"}} for doc in docs]
     except Exception as e:
         print(f"MongoDB 查询所有 ai_config 失败: {e}")
-        return []
+        return []

+ 6 - 2
app/db/redis_client.py

@@ -2,9 +2,13 @@ import redis
 import json
 import requests
 from typing import Optional
+from dotenv import load_dotenv
+import os
 
-REDIS_HOST = "r-2zeitjlg0gdypzb4v6.redis.rds.aliyuncs.com"
-REDIS_PORT = 6379
+load_dotenv()
+
+REDIS_HOST = os.getenv("REDIS_HOST")
+REDIS_PORT = os.getenv("REDIS_PORT")
 REDIS_TTL = 1800  # 30分钟
 
 THIRD_PARTY_API = "http://eco.zhongsou.com/eco/user/user.redis.info.groovy"

+ 48 - 0
docker-compose.yml

@@ -0,0 +1,48 @@
+version: '3.8'
+
+services:
+  # FastAPI 应用
+  chat-ai-api:
+    build:
+      context: .
+      dockerfile: Dockerfile
+    image: chat-ai-api:latest
+    container_name: chat-ai-api
+    ports:
+      - "8000:8000"
+    environment:
+      # API 配置
+      ARK_API_KEY: ${ARK_API_KEY}
+      ARK_BASE_URL: ${ARK_BASE_URL}
+      MODEL_NAME: ${MODEL_NAME}
+      ROLE_DESCRIPTION: ${ROLE_DESCRIPTION}
+
+      # JWT 配置
+      SECRET_KEY: ${SECRET_KEY}
+      ALGORITHM: ${ALGORITHM}
+      ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-30}
+
+      # MongoDB 配置(云服务)
+      SOUYUE_MONGO_URI: ${SOUYUE_MONGO_URI}
+      ARK_LOGS_MONGO_URI: ${ARK_LOGS_MONGO_URI}
+
+      # Redis 配置(云服务)
+      REDIS_HOST: ${REDIS_HOST}
+      REDIS_PORT: ${REDIS_PORT:-6379}
+
+      # 应用配置
+      LOG_LEVEL: ${LOG_LEVEL:-info}
+      ENVIRONMENT: ${ENVIRONMENT:-production}
+
+    restart: unless-stopped
+
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+      start_period: 5s
+
+networks:
+  default:
+    driver: bridge