From e110067840dde1c4ad054b06a8e363b0e8cad568 Mon Sep 17 00:00:00 2001 From: yuliang_guo Date: Tue, 3 Feb 2026 14:25:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E8=84=9A=E6=9C=AC=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F=E9=85=8D?= =?UTF-8?q?=E7=BD=AEworkers=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 start.sh 启动脚本,根据 WORKERS/RELOAD 环境变量自动配置 - 修改 Dockerfile 使用启动脚本,默认 WORKERS=4 - 更新 docker-compose.prod-multi.yml,所有租户使用环境变量配置 - 生产环境默认4个workers,提升并发处理能力 Co-authored-by: Cursor --- backend/Dockerfile | 13 +++- backend/start.sh | 86 +++++++-------------- deploy/docker/docker-compose.prod-multi.yml | 28 ++++--- 3 files changed, 58 insertions(+), 69 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 6ecb944..c8b295d 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -43,9 +43,18 @@ RUN pip install --upgrade pip && \ # 复制应用代码 COPY app/ ./app/ +# 复制启动脚本 +COPY start.sh ./start.sh +RUN chmod +x ./start.sh + # 创建上传目录和日志目录 RUN mkdir -p uploads logs +# 默认环境变量(可通过docker-compose或环境变量覆盖) +ENV WORKERS=4 \ + RELOAD=false \ + TIMEOUT_KEEP_ALIVE=600 + # 暴露端口 EXPOSE 8000 @@ -53,5 +62,5 @@ EXPOSE 8000 HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8000/health || exit 1 -# 启动命令(生产模式,无热重载) -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4", "--timeout-keep-alive", "600"] \ No newline at end of file +# 使用启动脚本 +CMD ["./start.sh"] \ No newline at end of file diff --git a/backend/start.sh b/backend/start.sh index a064430..000fc97 100644 --- a/backend/start.sh +++ b/backend/start.sh @@ -1,64 +1,38 @@ #!/bin/bash +# 统一启动脚本 - 根据环境变量自动配置 -# 颜色定义 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color +# 默认配置 +HOST=${HOST:-0.0.0.0} +PORT=${PORT:-8000} +WORKERS=${WORKERS:-1} +RELOAD=${RELOAD:-false} +TIMEOUT_KEEP_ALIVE=${TIMEOUT_KEEP_ALIVE:-600} -echo -e "${GREEN}考培练系统后端启动脚本${NC}" -echo "================================" +echo "==============================================" +echo " KaoPeiLian Backend Starting..." +echo "==============================================" +echo " HOST: $HOST" +echo " PORT: $PORT" +echo " WORKERS: $WORKERS" +echo " RELOAD: $RELOAD" +echo " TIMEOUT_KEEP_ALIVE: $TIMEOUT_KEEP_ALIVE" +echo "==============================================" -# 检查Python版本 -echo -e "${YELLOW}检查Python版本...${NC}" -python_version=$(python3 --version 2>&1) -if [[ $? -eq 0 ]]; then - echo -e "${GREEN}✓ $python_version${NC}" +# 构建启动命令 +CMD="uvicorn app.main:app --host $HOST --port $PORT --timeout-keep-alive $TIMEOUT_KEEP_ALIVE" + +if [ "$RELOAD" = "true" ]; then + # 开发模式:启用热重载(不支持多workers) + CMD="$CMD --reload --reload-dir /app/app" + echo "Mode: Development (hot reload enabled)" else - echo -e "${RED}✗ Python3未安装${NC}" - exit 1 + # 生产模式:多workers + CMD="$CMD --workers $WORKERS" + echo "Mode: Production ($WORKERS workers)" fi -# 检查虚拟环境 -if [ ! -d "venv" ]; then - echo -e "${YELLOW}创建虚拟环境...${NC}" - python3 -m venv venv -fi +echo "" +echo "Executing: $CMD" +echo "" -# 激活虚拟环境 -echo -e "${YELLOW}激活虚拟环境...${NC}" -source venv/bin/activate - -# 安装依赖 -echo -e "${YELLOW}安装依赖...${NC}" -pip install -q -r requirements/base.txt - -# 检查.env文件 -if [ ! -f ".env" ]; then - echo -e "${YELLOW}创建.env文件...${NC}" - cp .env.example .env - echo -e "${GREEN}✓ 已创建.env文件,请根据需要修改配置${NC}" -fi - -# 检查数据库连接 -echo -e "${YELLOW}检查数据库连接...${NC}" -python -c " -import os -from dotenv import load_dotenv -load_dotenv() -db_url = os.getenv('DATABASE_URL', '') -if 'mysql' in db_url: - print('✓ 数据库配置已设置') -else: - print('⚠ 请检查数据库配置') -" 2>/dev/null - -# 启动服务 -echo -e "${GREEN}启动开发服务器...${NC}" -echo "================================" -echo -e "API文档: ${GREEN}http://localhost:8000/api/docs${NC}" -echo -e "健康检查: ${GREEN}http://localhost:8000/health${NC}" -echo "================================" - -# 启动uvicorn -uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 +exec $CMD diff --git a/deploy/docker/docker-compose.prod-multi.yml b/deploy/docker/docker-compose.prod-multi.yml index b427850..657b249 100644 --- a/deploy/docker/docker-compose.prod-multi.yml +++ b/deploy/docker/docker-compose.prod-multi.yml @@ -78,16 +78,17 @@ services: environment: - TZ=Asia/Shanghai - PYTHONPATH=/app + - WORKERS=4 # 生产环境4个workers + - RELOAD=false # 生产环境关闭热重载 ports: - "8010:8000" volumes: - - ./kaopeilian-backend/app:/app/app # 代码热重载 + - ./kaopeilian-backend/app:/app/app - /data/prod-envs/uploads-hua:/app/uploads - /data/prod-envs/logs-hua:/app/logs - /data/prod-envs/secrets:/app/secrets:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] networks: - prod-network - kaopeilian-network @@ -164,16 +165,17 @@ services: environment: - TZ=Asia/Shanghai - PYTHONPATH=/app + - WORKERS=4 + - RELOAD=false ports: - "8011:8000" volumes: - - ./kaopeilian-backend/app:/app/app # 代码热重载 + - ./kaopeilian-backend/app:/app/app - /data/prod-envs/uploads-yy:/app/uploads - /data/prod-envs/logs-yy:/app/logs - /data/prod-envs/secrets:/app/secrets:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] networks: - prod-network - kaopeilian-network @@ -250,16 +252,17 @@ services: environment: - TZ=Asia/Shanghai - PYTHONPATH=/app + - WORKERS=4 + - RELOAD=false ports: - "8012:8000" volumes: - - ./kaopeilian-backend/app:/app/app # 代码热重载 + - ./kaopeilian-backend/app:/app/app - /data/prod-envs/uploads-hl:/app/uploads - /data/prod-envs/logs-hl:/app/logs - /data/prod-envs/secrets:/app/secrets:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] networks: - prod-network - kaopeilian-network @@ -336,16 +339,17 @@ services: environment: - TZ=Asia/Shanghai - PYTHONPATH=/app + - WORKERS=4 + - RELOAD=false ports: - "8013:8000" volumes: - - ./kaopeilian-backend/app:/app/app # 代码热重载 + - ./kaopeilian-backend/app:/app/app - /data/prod-envs/uploads-xy:/app/uploads - /data/prod-envs/logs-xy:/app/logs - /data/prod-envs/secrets:/app/secrets:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] networks: - prod-network - kaopeilian-network @@ -423,16 +427,17 @@ services: environment: - TZ=Asia/Shanghai - PYTHONPATH=/app + - WORKERS=4 + - RELOAD=false ports: - "8014:8000" volumes: - - ./kaopeilian-backend/app:/app/app # 代码热重载 + - ./kaopeilian-backend/app:/app/app - /data/prod-envs/uploads-fw:/app/uploads - /data/prod-envs/logs-fw:/app/logs - /data/prod-envs/secrets:/app/secrets:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] networks: - prod-network - kaopeilian-network @@ -508,6 +513,8 @@ services: environment: - TZ=Asia/Shanghai - PYTHONPATH=/app + - WORKERS=4 + - RELOAD=false ports: - "8016:8000" volumes: @@ -517,7 +524,6 @@ services: - /data/prod-envs/secrets:/app/secrets:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] networks: - prod-network - kaopeilian-network