添加 Docker 部署支持和环境变量配置

添加了完整的 Docker 部署方案,包括:
- 创建 .env.example 环境变量配置模板文件
- 新增 docker-compose.yml 用于全栈服务编排
- 为前后端分别创建 Dockerfile 实现容器化部署
- 添加 nginx.conf 配置前端反向代理
- 在 README.md 中详细说明 Docker 部署流程
- 集成 Celery 任务队列支持异步处理
- 配置多数据库服务 (MongoDB, MySQL, Redis) 的连接
- 实现健康检查和服务依赖管理
This commit is contained in:
2026-04-21 20:39:12 +08:00
parent be302839ee
commit d2e3c2db3e
7 changed files with 459 additions and 0 deletions

35
.env.example Normal file
View File

@@ -0,0 +1,35 @@
# ============================================================
# FilesReadSystem 环境变量配置模板
# 复制此文件为 .env 并填入实际值
# ============================================================
# ==================== 应用配置 ====================
DEBUG=false
# ==================== MongoDB ====================
MONGO_ROOT_USER=admin
MONGO_ROOT_PASSWORD=your_mongo_password
MONGODB_DB_NAME=document_system
# ==================== MySQL ====================
MYSQL_PASSWORD=your_mysql_password
MYSQL_DATABASE=document
# ==================== Redis ====================
REDIS_PASSWORD=your_redis_password
# ==================== LLM AI ====================
LLM_API_KEY=your_llm_api_key
LLM_BASE_URL=https://api.deepseek.com
LLM_MODEL_NAME=deepseek-chat
# ==================== Supabase ====================
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your_anon_key
SUPABASE_SERVICE_KEY=your_service_key
# ==================== Embedding / RAG ====================
EMBEDDING_MODEL=all-MiniLM-L6-v2
# ==================== 前端配置 ====================
VITE_APP_ID=your_app_id

View File

@@ -233,6 +233,77 @@ pnpm dev
--- ---
## Docker 部署 / Docker Deployment
### 快速启动 / Quick Start
```bash
# 1. 复制环境变量模板并编辑
cp .env.example .env
# 编辑 .env 填入实际配置
# 2. 启动所有服务
docker compose up -d
# 3. 查看日志
docker compose logs -f
# 4. 检查服务状态
docker compose ps
# 5. 更新部署
docker compose up -d --build
```
### 服务说明 / Services
| 服务 | 端口 | 说明 |
|:---|:---|:---|
| frontend | 80 | React 前端 (Nginx) |
| backend | 8000 | FastAPI 后端 |
| mongodb | 27017 | MongoDB 数据库 |
| mysql | 3306 | MySQL 数据库 |
| redis | 6379 | Redis 缓存/队列 |
### 环境变量 / Environment Variables
创建 `.env` 文件,参考 `.env.example`:
```bash
# 数据库配置
MONGO_ROOT_USER=admin
MONGO_ROOT_PASSWORD=your_password
MONGODB_DB_NAME=document_system
MYSQL_PASSWORD=your_password
MYSQL_DATABASE=document
REDIS_PASSWORD=your_password
# LLM 配置
LLM_API_KEY=your_api_key
LLM_BASE_URL=https://api.deepseek.com
LLM_MODEL_NAME=deepseek-chat
# Supabase 配置
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your_anon_key
SUPABASE_SERVICE_KEY=your_service_key
```
### 验证部署 / Verify Deployment
```bash
# 检查所有服务状态
docker compose ps
# 访问前端
curl http://localhost
# 检查后端健康
curl http://localhost:8000/health
```
---
## 许可证 / License ## 许可证 / License
ISC ISC

40
backend/Dockerfile Normal file
View File

@@ -0,0 +1,40 @@
# ============================================================
# FilesReadSystem Backend Docker Image
# ============================================================
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# 安装系统依赖 (FAISS, Pillow, tesseract 等)
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
g++ \
libgl1-mesa-glx \
libglib2.0-0 \
tesseract-ocr \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# 先复制依赖文件,再安装(利用 Docker 缓存)
COPY requirements.txt .
# 安装 Python 依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY app/ ./app/
# 创建数据目录
RUN mkdir -p /app/data/uploads /app/data/faiss /app/data/logs
# 暴露端口
EXPOSE 8000
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD python -c "import httpx; httpx.get('http://localhost:8000/health')" || exit 1
# 启动命令
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

27
backend/app/celery_app.py Normal file
View File

@@ -0,0 +1,27 @@
# ============================================================
# Celery 应用配置
# ============================================================
from celery import Celery
# 优先使用环境变量,否则使用默认值
import os
CELERY_BROKER_URL = os.getenv("CELERY_BROKER_URL", "redis://localhost:6379/1")
CELERY_RESULT_BACKEND = os.getenv("CELERY_RESULT_BACKEND", "redis://localhost:6379/2")
celery_app = Celery(
"filesread",
broker=CELERY_BROKER_URL,
backend=CELERY_RESULT_BACKEND,
)
celery_app.conf.update(
task_serializer="json",
accept_content=["json"],
result_serializer="json",
timezone="Asia/Shanghai",
enable_utc=True,
task_track_started=True,
task_time_limit=3600, # 1小时超时
worker_prefetch_multiplier=1,
)

203
docker-compose.yml Normal file
View File

@@ -0,0 +1,203 @@
# ============================================================
# FilesReadSystem Docker Compose
# 全栈 AI 文档理解与数据融合系统
# ============================================================
version: "3.8"
services:
# ==================== 数据库服务 ====================
mongodb:
image: mongo:7.0
container_name: filesread_mongodb
restart: unless-stopped
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER:-admin}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD:-20060825fhy}
MONGO_INITDB_DATABASE: ${MONGODB_DB_NAME:-document_system}
volumes:
- mongodb_data:/data/db
networks:
- filesread_network
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')", "--quiet"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
mysql:
image: mysql:8.0
container_name: filesread_mysql
restart: unless-stopped
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD:-123456}
MYSQL_DATABASE: ${MYSQL_DATABASE:-document}
volumes:
- mysql_data:/var/lib/mysql
networks:
- filesread_network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_PASSWORD:-123456}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
redis:
image: redis:7-alpine
container_name: filesread_redis
restart: unless-stopped
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- filesread_network
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-}
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# ==================== 应用服务 ====================
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: filesread_backend
restart: unless-stopped
ports:
- "8000:8000"
environment:
# 应用配置
APP_NAME: FilesReadSystem
DEBUG: ${DEBUG:-false}
API_V1_STR: /api/v1
# MongoDB 配置 (使用 docker-compose 服务名)
MONGODB_URL: mongodb://${MONGO_ROOT_USER:-admin}:${MONGO_ROOT_PASSWORD:-20060825fhy}@mongodb:27017/admin
MONGODB_DB_NAME: ${MONGODB_DB_NAME:-document_system}
# MySQL 配置
MYSQL_HOST: mysql
MYSQL_PORT: 3306
MYSQL_USER: root
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-123456}
MYSQL_DATABASE: ${MYSQL_DATABASE:-document}
MYSQL_CHARSET: utf8mb4
# Redis 配置
REDIS_URL: redis://:${REDIS_PASSWORD:-}@redis:6379/0
# LLM AI 配置
LLM_API_KEY: ${LLM_API_KEY}
LLM_BASE_URL: ${LLM_BASE_URL:-https://api.deepseek.com}
LLM_MODEL_NAME: ${LLM_MODEL_NAME:-deepseek-chat}
# Supabase 配置
SUPABASE_URL: ${SUPABASE_URL}
SUPABASE_ANON_KEY: ${SUPABASE_ANON_KEY}
SUPABASE_SERVICE_KEY: ${SUPABASE_SERVICE_KEY}
# Embedding / RAG 配置
EMBEDDING_MODEL: ${EMBEDDING_MODEL:-all-MiniLM-L6-v2}
FAISS_INDEX_DIR: /app/data/faiss
# 文件路径配置
UPLOAD_DIR: /app/data/uploads
MAX_UPLOAD_SIZE: 104857600
# Celery 配置
CELERY_BROKER_URL: redis://:${REDIS_PASSWORD:-}@redis:6379/1
CELERY_RESULT_BACKEND: redis://:${REDIS_PASSWORD:-}@redis:6379/2
volumes:
- backend_data:/app/data
networks:
- filesread_network
depends_on:
mongodb:
condition: service_healthy
mysql:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "python", "-c", "import httpx; httpx.get('http://localhost:8000/health')"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
celery_worker:
build:
context: ./backend
dockerfile: Dockerfile
container_name: filesread_celery
restart: unless-stopped
command: celery -A app.celery_app worker --loglevel=info --prefetch-multiplier=1
environment:
# Celery 配置
CELERY_BROKER_URL: redis://:${REDIS_PASSWORD:-}@redis:6379/1
CELERY_RESULT_BACKEND: redis://:${REDIS_PASSWORD:-}@redis:6379/2
# 复用后端的数据库配置
MONGODB_URL: mongodb://${MONGO_ROOT_USER:-admin}:${MONGO_ROOT_PASSWORD:-20060825fhy}@mongodb:27017/admin
MONGODB_DB_NAME: ${MONGODB_DB_NAME:-document_system}
MYSQL_HOST: mysql
MYSQL_PORT: 3306
MYSQL_USER: root
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-123456}
MYSQL_DATABASE: ${MYSQL_DATABASE:-document}
REDIS_URL: redis://:${REDIS_PASSWORD:-}@redis:6379/0
# LLM 配置
LLM_API_KEY: ${LLM_API_KEY}
LLM_BASE_URL: ${LLM_BASE_URL:-https://api.deepseek.com}
LLM_MODEL_NAME: ${LLM_MODEL_NAME:-deepseek-chat}
# Embedding 配置
EMBEDDING_MODEL: ${EMBEDDING_MODEL:-all-MiniLM-L6-v2}
FAISS_INDEX_DIR: /app/data/faiss
volumes:
- backend_data:/app/data
networks:
- filesread_network
depends_on:
- redis
- mongodb
- mysql
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: filesread_frontend
restart: unless-stopped
ports:
- "80:80"
environment:
VITE_APP_ID: ${VITE_APP_ID:-}
VITE_SUPABASE_URL: ${SUPABASE_URL}
VITE_SUPABASE_ANON_KEY: ${SUPABASE_ANON_KEY}
VITE_BACKEND_API_URL: /api/v1
networks:
- filesread_network
depends_on:
- backend
networks:
filesread_network:
driver: bridge
volumes:
mongodb_data:
mysql_data:
redis_data:
backend_data:

36
frontend/Dockerfile Normal file
View File

@@ -0,0 +1,36 @@
# ============================================================
# FilesReadSystem Frontend - React + Vite
# 多阶段构建: Node 构建 -> Nginx 运行
# ============================================================
# === 阶段1: 构建阶段 ===
FROM node:20-alpine AS builder
WORKDIR /app
# 复制 package 文件和锁文件
COPY package.json pnpm-lock.yaml* ./
# 安装 pnpm 并安装依赖
RUN npm install -g pnpm && \
pnpm install --frozen-lockfile
# 复制源码
COPY . .
# 构建生产版本
RUN pnpm build
# === 阶段2: 运行阶段 ===
FROM nginx:alpine
# 复制 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html
# 暴露端口
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

47
frontend/nginx.conf Normal file
View File

@@ -0,0 +1,47 @@
# ============================================================
# FilesReadSystem Nginx 配置
# 反向代理 API 请求到后端
# ============================================================
server {
listen 80;
server_name localhost;
# 前端静态文件
root /usr/share/nginx/html;
index index.html;
# SPA 支持 - 所有请求都尝试返回 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# API 反向代理到后端
location /api/ {
proxy_pass http://backend:8000/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 文件上传代理
location /uploads/ {
proxy_pass http://backend:8000/uploads/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 100M;
}
}