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 = {
|
DATABASE_CONFIG = {
|
||||||
'host': os.getenv('DB_HOST', 'localhost'),
|
'host': os.getenv('DB_HOST', 'localhost'),
|
||||||
'user': os.getenv('DB_USER', 'root'),
|
'user': os.getenv('DB_USER', 'root'),
|
||||||
'password': os.getenv('DB_PASSWORD', ''),
|
'password': os.getenv('DB_PASSWORD', 'sagacity'),
|
||||||
'database': os.getenv('DB_NAME', 'imeeting'),
|
'database': os.getenv('DB_NAME', 'imeeting'),
|
||||||
'port': int(os.getenv('DB_PORT', '3306')),
|
'port': int(os.getenv('DB_PORT', '3306')),
|
||||||
'charset': 'utf8mb4'
|
'charset': 'utf8mb4'
|
||||||
|
|
@ -31,8 +31,7 @@ DATABASE_CONFIG = {
|
||||||
# API配置
|
# API配置
|
||||||
API_CONFIG = {
|
API_CONFIG = {
|
||||||
'host': os.getenv('API_HOST', '0.0.0.0'),
|
'host': os.getenv('API_HOST', '0.0.0.0'),
|
||||||
'port': int(os.getenv('API_PORT', '8000')),
|
'port': int(os.getenv('API_PORT', '8000'))
|
||||||
'cors_origins': os.getenv('CORS_ORIGINS', 'http://localhost:5173').split(',')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# 七牛云配置
|
# 七牛云配置
|
||||||
|
|
|
||||||
|
|
@ -2,24 +2,14 @@
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
from mysql.connector import Error
|
from mysql.connector import Error
|
||||||
|
from app.core.config import DATABASE_CONFIG
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
DB_CONFIG = {
|
|
||||||
'host': 'localhost',
|
|
||||||
'database': 'imeeting',
|
|
||||||
'user': 'root',
|
|
||||||
'password': 'sagacity',
|
|
||||||
'port': 3306,
|
|
||||||
'charset': 'utf8mb4',
|
|
||||||
'autocommit': False, # 禁用自动提交
|
|
||||||
'consume_results': True # 自动消费未读结果
|
|
||||||
}
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def get_db_connection():
|
def get_db_connection():
|
||||||
connection = None
|
connection = None
|
||||||
try:
|
try:
|
||||||
connection = mysql.connector.connect(**DB_CONFIG)
|
connection = mysql.connector.connect(**DATABASE_CONFIG)
|
||||||
yield connection
|
yield connection
|
||||||
except Error as e:
|
except Error as e:
|
||||||
print(f"数据库连接错误: {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
|
import uvicorn
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI, Request, HTTPException
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from app.api.endpoints import auth, users, meetings
|
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
|
import os
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
|
|
@ -12,10 +12,23 @@ app = FastAPI(
|
||||||
version="1.0.0"
|
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中间件
|
# 添加CORS中间件
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins=API_CONFIG['cors_origins'],
|
# allow_origins=API_CONFIG['cors_origins'],
|
||||||
allow_credentials=True,
|
allow_credentials=True,
|
||||||
allow_methods=["*"],
|
allow_methods=["*"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
|
|
@ -34,5 +47,26 @@ app.include_router(meetings.router, prefix="/api", tags=["Meetings"])
|
||||||
def read_root():
|
def read_root():
|
||||||
return {"message": "Welcome to iMeeting API"}
|
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__":
|
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