添加 Docker 部署支持和环境变量配置
添加了完整的 Docker 部署方案,包括: - 创建 .env.example 环境变量配置模板文件 - 新增 docker-compose.yml 用于全栈服务编排 - 为前后端分别创建 Dockerfile 实现容器化部署 - 添加 nginx.conf 配置前端反向代理 - 在 README.md 中详细说明 Docker 部署流程 - 集成 Celery 任务队列支持异步处理 - 配置多数据库服务 (MongoDB, MySQL, Redis) 的连接 - 实现健康检查和服务依赖管理
This commit is contained in:
35
.env.example
Normal file
35
.env.example
Normal 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
|
||||
71
README.md
71
README.md
@@ -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
|
||||
|
||||
ISC
|
||||
|
||||
40
backend/Dockerfile
Normal file
40
backend/Dockerfile
Normal 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
27
backend/app/celery_app.py
Normal 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
203
docker-compose.yml
Normal 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
36
frontend/Dockerfile
Normal 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
47
frontend/nginx.conf
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user