v1.0.2
parent
d85f12fb9d
commit
d6602435c4
|
|
@ -0,0 +1,31 @@
|
|||
# 使用Python 3.9.6基础镜像
|
||||
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/python:3.12.9-slim
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 设置环境变量
|
||||
ENV PYTHONPATH=/app
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# 安装系统依赖
|
||||
RUN apt-get update && apt-get install -y \
|
||||
gcc \
|
||||
default-libmysqlclient-dev \
|
||||
pkg-config \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 复制依赖文件
|
||||
COPY requirements-prod.txt .
|
||||
|
||||
# 安装Python依赖
|
||||
RUN pip install --no-cache-dir -r requirements-prod.txt
|
||||
|
||||
# 复制应用代码
|
||||
COPY . .
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 8001
|
||||
|
||||
# 启动命令
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8001"]
|
||||
|
|
@ -22,7 +22,7 @@ MARKDOWN_DIR.mkdir(exist_ok=True)
|
|||
DATABASE_CONFIG = {
|
||||
'host': os.getenv('DB_HOST', 'localhost'),
|
||||
'user': os.getenv('DB_USER', 'root'),
|
||||
'password': os.getenv('DB_PASSWORD', ''),
|
||||
'password': os.getenv('DB_PASSWORD', 'sagacity'),
|
||||
'database': os.getenv('DB_NAME', 'imeeting'),
|
||||
'port': int(os.getenv('DB_PORT', '3306')),
|
||||
'charset': 'utf8mb4'
|
||||
|
|
@ -31,8 +31,7 @@ DATABASE_CONFIG = {
|
|||
# API配置
|
||||
API_CONFIG = {
|
||||
'host': os.getenv('API_HOST', '0.0.0.0'),
|
||||
'port': int(os.getenv('API_PORT', '8000')),
|
||||
'cors_origins': os.getenv('CORS_ORIGINS', 'http://localhost:5173').split(',')
|
||||
'port': int(os.getenv('API_PORT', '8000'))
|
||||
}
|
||||
|
||||
# 七牛云配置
|
||||
|
|
|
|||
|
|
@ -2,24 +2,14 @@
|
|||
from fastapi import HTTPException
|
||||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
from app.core.config import DATABASE_CONFIG
|
||||
from contextlib import contextmanager
|
||||
|
||||
DB_CONFIG = {
|
||||
'host': 'localhost',
|
||||
'database': 'imeeting',
|
||||
'user': 'root',
|
||||
'password': 'sagacity',
|
||||
'port': 3306,
|
||||
'charset': 'utf8mb4',
|
||||
'autocommit': False, # 禁用自动提交
|
||||
'consume_results': True # 自动消费未读结果
|
||||
}
|
||||
|
||||
@contextmanager
|
||||
def get_db_connection():
|
||||
connection = None
|
||||
try:
|
||||
connection = mysql.connector.connect(**DB_CONFIG)
|
||||
connection = mysql.connector.connect(**DATABASE_CONFIG)
|
||||
yield connection
|
||||
except Error as e:
|
||||
print(f"数据库连接错误: {e}")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "🚀 开始部署iMeeting后端服务..."
|
||||
|
||||
# 检查虚拟环境
|
||||
if [ ! -d "venv" ]; then
|
||||
echo "❌ 虚拟环境不存在!请先创建虚拟环境"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ 发现虚拟环境,继续部署..."
|
||||
|
||||
# 停止并删除现有容器
|
||||
echo "📦 停止现有容器..."
|
||||
docker-compose -f docker-compose.prod.yml down
|
||||
|
||||
# 构建新镜像
|
||||
echo "🔨 构建Docker镜像..."
|
||||
docker-compose -f docker-compose.prod.yml build --no-cache
|
||||
|
||||
# 启动服务
|
||||
echo "▶️ 启动服务..."
|
||||
docker-compose -f docker-compose.prod.yml up -d
|
||||
|
||||
# 检查服务状态
|
||||
echo "🔍 检查服务状态..."
|
||||
sleep 10
|
||||
docker-compose -f docker-compose.prod.yml ps
|
||||
|
||||
# 检查健康状态
|
||||
echo "🏥 检查健康状态..."
|
||||
curl -f http://localhost:8001/health && echo "✅ 后端服务健康检查通过" || echo "❌ 后端服务健康检查失败"
|
||||
|
||||
echo ""
|
||||
echo "🎉 部署完成!"
|
||||
echo "🔧 后端服务访问地址: http://localhost:8001"
|
||||
echo "📊 查看日志: docker-compose -f docker-compose.prod.yml logs -f"
|
||||
echo "🛑 停止服务: docker-compose -f docker-compose.prod.yml down"
|
||||
echo ""
|
||||
echo "💡 提示:如需更新后端,请:"
|
||||
echo " 1. 修改代码后运行 ./deploy-prod.sh 重新部署"
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
imeeting-backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "8001:8001"
|
||||
environment:
|
||||
# Python运行环境
|
||||
- PYTHONPATH=/app
|
||||
- PYTHONUNBUFFERED=1
|
||||
|
||||
# 数据库配置
|
||||
- DB_HOST=host.docker.internal
|
||||
- DB_USER=root
|
||||
- DB_PASSWORD=sagacity
|
||||
- DB_NAME=imeeting
|
||||
- DB_PORT=3306
|
||||
|
||||
# Redis配置
|
||||
- REDIS_HOST=host.docker.internal
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_DB=6
|
||||
- REDIS_PASSWORD=
|
||||
|
||||
# API配置
|
||||
- API_HOST=0.0.0.0
|
||||
- API_PORT=8001
|
||||
|
||||
# 应用配置
|
||||
- BASE_URL=http://imeeting.unisspace.com
|
||||
|
||||
# 七牛云配置
|
||||
- QINIU_ACCESS_KEY=A0tp96HCtg-wZCughTgi5vc2pJnw3btClwxRE_e8
|
||||
- QINIU_SECRET_KEY=Lj-MSHpaVbmzpS86kMIjmwikvYOT9iPBjCk9hm6k
|
||||
- QINIU_BUCKET=imeeting
|
||||
- QINIU_DOMAIN=t0vogyxkz.hn-bkt.clouddn.com
|
||||
|
||||
# LLM配置
|
||||
- QWEN_API_KEY=sk-c2bf06ea56b4491ea3d1e37fdb472b8f
|
||||
- LLM_MODEL_NAME=qwen-plus
|
||||
- LLM_API_URL=https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation
|
||||
- LLM_MAX_TOKENS=2000
|
||||
- LLM_TEMPERATURE=0.7
|
||||
- LLM_TOP_P=0.9
|
||||
|
||||
volumes:
|
||||
# 挂载上传目录保持数据持久化
|
||||
- ./uploads:/app/uploads
|
||||
restart: unless-stopped
|
||||
container_name: imeeting-backend
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8001/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
42
main.py
42
main.py
|
|
@ -1,9 +1,9 @@
|
|||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from fastapi import FastAPI, Request, HTTPException
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from app.api.endpoints import auth, users, meetings
|
||||
from app.core.config import UPLOAD_DIR, API_CONFIG
|
||||
from app.core.config import UPLOAD_DIR, API_CONFIG, MAX_FILE_SIZE
|
||||
import os
|
||||
|
||||
app = FastAPI(
|
||||
|
|
@ -12,10 +12,23 @@ app = FastAPI(
|
|||
version="1.0.0"
|
||||
)
|
||||
|
||||
# 添加请求体大小检查中间件
|
||||
@app.middleware("http")
|
||||
async def check_content_size(request: Request, call_next):
|
||||
# 检查Content-Length头
|
||||
content_length = request.headers.get("content-length")
|
||||
if content_length:
|
||||
content_length = int(content_length)
|
||||
if content_length > MAX_FILE_SIZE:
|
||||
raise HTTPException(status_code=413, detail=f"Request entity too large. Maximum size is {MAX_FILE_SIZE//1024//1024}MB")
|
||||
|
||||
response = await call_next(request)
|
||||
return response
|
||||
|
||||
# 添加CORS中间件
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=API_CONFIG['cors_origins'],
|
||||
# allow_origins=API_CONFIG['cors_origins'],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
|
|
@ -34,5 +47,26 @@ app.include_router(meetings.router, prefix="/api", tags=["Meetings"])
|
|||
def read_root():
|
||||
return {"message": "Welcome to iMeeting API"}
|
||||
|
||||
@app.get("/health")
|
||||
def health_check():
|
||||
"""健康检查端点"""
|
||||
return {
|
||||
"status": "healthy",
|
||||
"service": "iMeeting API",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(app, host=API_CONFIG['host'], port=API_CONFIG['port'])
|
||||
# 简单的uvicorn配置,避免参数冲突
|
||||
uvicorn.run(
|
||||
"main:app",
|
||||
host=API_CONFIG['host'],
|
||||
port=API_CONFIG['port'],
|
||||
limit_max_requests=1000,
|
||||
timeout_keep_alive=30,
|
||||
reload=True,
|
||||
# 设置更大的请求体限制以支持音频文件上传
|
||||
h11_max_incomplete_event_size=104857600, # 100MB
|
||||
|
||||
|
||||
)
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
aiohappyeyeballs==2.6.1
|
||||
aiohttp==3.12.15
|
||||
aiosignal==1.4.0
|
||||
annotated-types==0.7.0
|
||||
anyio==3.7.1
|
||||
async-timeout==5.0.1
|
||||
attrs==25.3.0
|
||||
bcrypt==4.3.0
|
||||
certifi==2025.8.3
|
||||
cffi==1.17.1
|
||||
charset-normalizer==3.4.3
|
||||
click==8.1.8
|
||||
cryptography==45.0.6
|
||||
dashscope==1.24.1
|
||||
distro==1.9.0
|
||||
dnspython==2.7.0
|
||||
ecdsa==0.19.1
|
||||
email_validator==2.2.0
|
||||
exceptiongroup==1.3.0
|
||||
fastapi==0.104.1
|
||||
frozenlist==1.7.0
|
||||
h11==0.16.0
|
||||
httpcore==1.0.9
|
||||
httptools==0.6.4
|
||||
httpx==0.28.1
|
||||
idna==3.10
|
||||
jiter==0.10.0
|
||||
multidict==6.6.4
|
||||
mysql-connector-python==8.2.0
|
||||
openai==1.99.9
|
||||
passlib==1.7.4
|
||||
propcache==0.3.2
|
||||
protobuf==4.21.12
|
||||
pyasn1==0.6.1
|
||||
pycparser==2.22
|
||||
pydantic==2.5.0
|
||||
pydantic_core==2.14.1
|
||||
PyJWT==2.10.1
|
||||
python-dotenv==1.1.1
|
||||
python-jose==3.5.0
|
||||
python-multipart==0.0.6
|
||||
PyYAML==6.0.2
|
||||
qiniu==7.17.0
|
||||
redis==6.4.0
|
||||
requests==2.32.4
|
||||
rsa==4.9.1
|
||||
six==1.17.0
|
||||
sniffio==1.3.1
|
||||
starlette==0.27.0
|
||||
tqdm==4.67.1
|
||||
typing_extensions==4.14.1
|
||||
urllib3==2.5.0
|
||||
uvicorn==0.24.0
|
||||
uvloop==0.21.0
|
||||
watchfiles==1.1.0
|
||||
websocket-client==1.8.0
|
||||
websockets==15.0.1
|
||||
yarl==1.20.1
|
||||
Loading…
Reference in New Issue