#!/bin/bash # 智能项目定价模型 - 生产环境部署脚本 # 遵循瑞小美部署规范 set -e # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # 检查必要命令 check_requirements() { log_info "检查环境依赖..." local requirements=("docker" "docker-compose") for cmd in "${requirements[@]}"; do if ! command -v $cmd &> /dev/null; then log_error "$cmd 未安装" exit 1 fi done log_info "环境检查通过" } # 检查 .env 文件 check_env_file() { log_info "检查环境配置..." if [ ! -f ".env" ]; then log_error ".env 文件不存在,请从 env.example 复制并配置" log_info "执行: cp env.example .env && chmod 600 .env" exit 1 fi # 检查 .env 文件权限 local perms=$(stat -c %a .env 2>/dev/null || stat -f %OLp .env 2>/dev/null) if [ "$perms" != "600" ]; then log_warn ".env 文件权限不是 600,正在修复..." chmod 600 .env fi # 检查必要配置项 local required_vars=("DATABASE_URL" "MYSQL_ROOT_PASSWORD" "MYSQL_PASSWORD" "SECRET_KEY") source .env for var in "${required_vars[@]}"; do if [ -z "${!var}" ]; then log_error "缺少必要配置: $var" exit 1 fi done # 检查是否修改了默认密码 if [[ "$SECRET_KEY" == *"change-in-production"* ]]; then log_error "请修改 SECRET_KEY 为随机字符串" exit 1 fi log_info "配置检查通过" } # 检查网络 check_network() { log_info "检查 Docker 网络..." # 检查 scrm_network 是否存在 if ! docker network ls | grep -q "scrm_network"; then log_info "创建 scrm_network 网络..." docker network create scrm_network fi log_info "网络检查通过" } # 拉取/构建镜像 build_images() { log_info "构建 Docker 镜像..." docker-compose build --no-cache log_info "镜像构建完成" } # 停止旧服务 stop_services() { log_info "停止旧服务..." docker-compose down --remove-orphans 2>/dev/null || true log_info "旧服务已停止" } # 启动服务 start_services() { log_info "启动服务..." docker-compose up -d log_info "服务启动中..." } # 等待服务就绪 wait_for_services() { log_info "等待服务就绪..." local max_attempts=30 local attempt=0 # 等待后端健康检查 while [ $attempt -lt $max_attempts ]; do if docker-compose exec -T pricing-backend curl -sf http://localhost:8000/health > /dev/null 2>&1; then log_info "后端服务就绪" break fi attempt=$((attempt + 1)) echo -n "." sleep 2 done if [ $attempt -eq $max_attempts ]; then log_error "服务启动超时" docker-compose logs --tail=50 exit 1 fi echo "" } # 刷新 Nginx DNS 缓存 refresh_nginx() { log_info "刷新 Nginx DNS 缓存..." # 检查 nginx_proxy 容器是否存在 if docker ps | grep -q "nginx_proxy"; then docker exec nginx_proxy nginx -s reload 2>/dev/null || log_warn "Nginx reload 失败,请手动执行" else log_warn "nginx_proxy 容器未运行,请确保 Nginx 配置正确" fi } # 显示服务状态 show_status() { log_info "服务状态:" echo "" docker-compose ps echo "" log_info "健康检查:" curl -sf http://localhost:8000/health 2>/dev/null && echo "" || log_warn "后端服务不可访问" echo "" log_info "部署完成!" echo "" echo "访问地址:" echo " - 前端: https://pricing.example.com (需配置 Nginx)" echo " - 后端 API: http://localhost:8000" echo " - API 文档: http://localhost:8000/docs (仅开发环境)" } # 回滚 rollback() { log_warn "执行回滚..." docker-compose down # 如果有备份,恢复 if [ -f ".env.backup" ]; then mv .env.backup .env fi log_info "回滚完成,请检查日志排查问题" } # 主函数 main() { local action="${1:-deploy}" cd "$(dirname "$0")/.." case $action in deploy) log_info "开始部署智能项目定价模型..." echo "" check_requirements check_env_file check_network build_images stop_services start_services wait_for_services refresh_nginx show_status ;; restart) log_info "重启服务..." docker-compose restart wait_for_services refresh_nginx show_status ;; stop) log_info "停止服务..." docker-compose down log_info "服务已停止" ;; status) show_status ;; logs) docker-compose logs -f --tail=100 ;; rollback) rollback ;; *) echo "用法: $0 {deploy|restart|stop|status|logs|rollback}" exit 1 ;; esac } # 捕获错误 trap 'log_error "部署失败"; exit 1' ERR main "$@"