This commit is contained in:
aaron 2025-03-21 23:02:15 +08:00
parent fd378b32c5
commit 9d6ba6cc29
5 changed files with 165 additions and 86 deletions

View File

@ -1,6 +1,9 @@
# 使用Python 3.10作为基础镜像 # 使用Python 3.10作为基础镜像
FROM python:3.10-slim FROM python:3.10-slim
# 设置工作目录
WORKDIR /app
# 设置时区 # 设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 清空所有默认源 # 清空所有默认源
@ -24,22 +27,42 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
build-essential \ build-essential \
default-libmysqlclient-dev \ default-libmysqlclient-dev \
default-mysql-client \
pkg-config \ pkg-config \
curl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# 设置工作目录
WORKDIR /app
# 复制项目文件 # 复制项目文件
COPY requirements.txt . COPY requirements.txt .
COPY app app/
# 显示当前的requirements.txt内容
RUN echo "========== requirements.txt content ==========" && \
cat requirements.txt && \
echo "=============================================="
# 安装Python依赖 # 安装Python依赖
RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt \ RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ --no-cache-dir -r requirements.txt \
&& pip install uvicorn && pip install -i https://mirrors.aliyun.com/pypi/simple/ --no-cache-dir uvicorn \
&& pip list
# 复制应用程序代码
COPY . .
# 添加执行权限
RUN chmod +x entrypoint.sh
# 设置PYTHONPATH
ENV PYTHONPATH=/app
# 暴露端口 # 暴露端口
EXPOSE 8000 EXPOSE 8000
# 启动命令 # 添加健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# 设置入口点
ENTRYPOINT ["/app/entrypoint.sh"]
# 默认命令
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@ -9,7 +9,23 @@ from urllib.parse import urljoin
from qcloud_cos import CosConfig, CosS3Client from qcloud_cos import CosConfig, CosS3Client
from qcloud_cos.cos_exception import CosServiceError, CosClientError from qcloud_cos.cos_exception import CosServiceError, CosClientError
import sts.sts
# 修改STS导入方式
try:
# 尝试直接从安装的包导入
from qcloud_python_sts.sts import Sts
except ImportError:
try:
# 尝试旧的导入方式
import sts.sts
Sts = sts.sts.Sts
except ImportError:
# 如果都不存在,记录错误
logging.error("无法导入腾讯云STS SDK请检查qcloud-python-sts是否已安装")
# 创建一个空类,避免运行时错误,但实际使用时会报错提示
class Sts:
def __init__(self, *args, **kwargs):
raise ImportError("腾讯云STS SDK未正确安装请执行 pip install qcloud-python-sts")
from app.utils.config import get_settings from app.utils.config import get_settings
@ -192,7 +208,7 @@ class QCloudCOSService:
} }
} }
sts_client = sts.sts.Sts(config) sts_client = Sts(config)
response = sts_client.get_credential() response = sts_client.get_credential()
return response return response

71
check_dependencies.py Executable file
View File

@ -0,0 +1,71 @@
#!/usr/bin/env python3
"""
依赖检查脚本 - 在应用启动前检查所有必要依赖是否已正确安装
"""
import importlib
import sys
import logging
# 配置日志
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger("依赖检查")
# 定义必要的依赖列表
REQUIRED_PACKAGES = [
("fastapi", "FastAPI框架"),
("uvicorn", "ASGI服务器"),
("sqlalchemy", "ORM数据库框架"),
("alembic", "数据库迁移工具"),
("pymysql", "MySQL驱动"),
("dashscope", "阿里云DashScope SDK"),
("qcloud_cos", "腾讯云COS SDK"),
("qcloud_python_sts", "腾讯云STS SDK", ["qcloud_python_sts.sts", "sts.sts"]),
("dotenv", "环境变量处理", ["dotenv", "python_dotenv"]),
]
def check_dependency(package_name, description, import_names=None):
"""检查依赖是否已安装"""
if import_names is None:
import_names = [package_name]
for import_name in import_names:
try:
importlib.import_module(import_name)
logger.info(f"{description} ({package_name}) 已安装")
return True
except ImportError:
continue
logger.error(f"{description} ({package_name}) 未安装或无法导入")
return False
def main():
"""检查所有依赖"""
logger.info("开始检查依赖...")
all_dependencies_ok = True
for package_info in REQUIRED_PACKAGES:
if len(package_info) == 2:
package_name, description = package_info
import_names = None
else:
package_name, description, import_names = package_info
if not check_dependency(package_name, description, import_names):
all_dependencies_ok = False
if all_dependencies_ok:
logger.info("所有依赖检查通过 ✓")
return 0
else:
logger.error("存在未安装或无法导入的依赖,请安装后再试")
logger.error("可以运行 pip install -r requirements.txt 安装所有依赖")
return 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,93 +1,61 @@
#!/bin/bash #!/bin/bash
set -e set -e
echo "正在启动AI Dressing服务..." # 显示当前环境
echo "============================================"
echo "容器启动 - 环境: ${ENV:-production}"
echo "============================================"
# 检查是否存在.env文件不存在则使用内置的.env.built # 检查是否存在.env文件
if [ ! -f ".env" ]; then if [ -f .env ]; then
echo "未找到.env文件使用构建时创建的.env.built文件" echo "从.env文件加载环境变量..."
if [ -f ".env.built" ]; then export $(grep -v '^#' .env | xargs)
cp .env.built .env
echo "已复制.env.built到.env"
else
echo "警告:未找到.env.built文件将使用系统环境变量"
fi
else
echo "使用已存在的.env文件"
fi fi
# 输出关键环境变量(隐藏敏感信息) # 检查关键环境变量
echo "检查关键环境变量:" echo "检查关键环境变量..."
# 数据库配置 MISSING_VARS=0
if [ -n "$DB_HOST" ]; then
echo "- DB_HOST: 已设置 ✓"
else
echo "- DB_HOST: 未设置 ❌"
fi
if [ -n "$DB_PORT" ]; then # 检查数据库配置
echo "- DB_PORT: 已设置 ✓" if [ -z "$DB_HOST" ]; then echo "警告: DB_HOST 未设置"; MISSING_VARS=$((MISSING_VARS+1)); fi
else if [ -z "$DB_USER" ]; then echo "警告: DB_USER 未设置"; MISSING_VARS=$((MISSING_VARS+1)); fi
echo "- DB_PORT: 未设置 ❌" if [ -z "$DB_PASSWORD" ]; then echo "警告: DB_PASSWORD 未设置"; MISSING_VARS=$((MISSING_VARS+1)); fi
fi if [ -z "$DB_NAME" ]; then echo "警告: DB_NAME 未设置"; MISSING_VARS=$((MISSING_VARS+1)); fi
if [ -n "$DB_NAME" ]; then # 检查API密钥
echo "- DB_NAME: 已设置 ✓" if [ -z "$DASHSCOPE_API_KEY" ]; then echo "警告: DASHSCOPE_API_KEY 未设置"; fi
else if [ -z "$QCLOUD_SECRET_ID" ]; then echo "警告: QCLOUD_SECRET_ID 未设置"; fi
echo "- DB_NAME: 未设置 ❌" if [ -z "$QCLOUD_SECRET_KEY" ]; then echo "警告: QCLOUD_SECRET_KEY 未设置"; fi
fi
# API密钥 # 检查依赖
if [ -n "$DASHSCOPE_API_KEY" ]; then echo "检查Python依赖..."
echo "- DASHSCOPE_API_KEY: 已设置(已隐藏) ✓" python3 check_dependencies.py
else
echo "- DASHSCOPE_API_KEY: 未设置 ❌"
fi
if [ -n "$QCLOUD_SECRET_ID" ] && [ -n "$QCLOUD_SECRET_KEY" ]; then # 如果主要依赖都在,尝试连接数据库
echo "- 腾讯云凭证: 已设置(已隐藏) ✓" if [ $MISSING_VARS -eq 0 ]; then
else echo "尝试连接到数据库..."
echo "- 腾讯云凭证: 未设置 ❌" MAX_RETRIES=5
fi RETRY_COUNT=0
# 检查依赖服务连接 until PGPASSWORD=$DB_PASSWORD mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" -e "SELECT 1" > /dev/null 2>&1; do
echo "检查数据库连接..." RETRY_COUNT=$((RETRY_COUNT+1))
MAX_RETRIES=10 if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
COUNT=0 echo "无法连接到数据库 - 达到最大重试次数"
if [ -n "$DB_HOST" ] && [ -n "$DB_PORT" ]; then
while [ $COUNT -lt $MAX_RETRIES ]; do
if nc -z -w3 $DB_HOST $DB_PORT; then
echo "数据库连接成功!"
break break
fi fi
echo "等待数据库连接... ($((COUNT+1))/$MAX_RETRIES)" echo "无法连接到数据库将在5秒后重试... ($RETRY_COUNT/$MAX_RETRIES)"
COUNT=$((COUNT+1)) sleep 5
sleep 2
done done
if [ $COUNT -eq $MAX_RETRIES ]; then if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
echo "警告:无法连接到数据库。服务将继续启动,但可能无法正常工作。" echo "数据库连接成功!"
# 应用数据库迁移
echo "应用数据库迁移..."
python3 create_migration.py upgrade
fi fi
else
echo "跳过数据库连接检查未设置DB_HOST或DB_PORT"
fi fi
# 应用数据库迁移 # 启动应用
echo "应用数据库迁移..." echo "启动API服务..."
if [ -f "create_migration.py" ]; then exec "$@"
python create_migration.py upgrade || echo "警告:数据库迁移失败,但将继续启动服务"
else
echo "未找到create_migration.py跳过数据库迁移"
fi
# 启动服务
echo "AI Dressing服务启动中..."
# 根据环境变量决定是否使用热重载
if [ "$ENV" = "development" ]; then
echo "以开发模式启动,启用热重载..."
exec uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
else
echo "以生产模式启动..."
exec uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
fi

View File

@ -17,6 +17,7 @@ dashscope>=1.5.0,<1.6.0
# 腾讯云SDK # 腾讯云SDK
cos-python-sdk-v5>=1.9.0,<2.0.0 cos-python-sdk-v5>=1.9.0,<2.0.0
qcloud-python-sts>=3.0.0,<4.0.0
# 工具库 # 工具库
python-dotenv>=0.19.1,<0.20.0 python-dotenv>=0.19.1,<0.20.0