#!/bin/bash set -e SERVER_IP="139.155.109.62" SERVER_USER="root" DEPLOY_ROOT="/home/novalon/docker-app" PROJECT_NAME="novalon-website" PROJECT_DIR="$DEPLOY_ROOT/$PROJECT_NAME" CONTAINER_NAME="novalon-website" NGINX_CONTAINER_NAME="novalon-nginx" VERSION="1.0.0" while getopts "i:u:p:c:v:h" opt; do case $opt in i) SERVER_IP="$OPTARG" ;; u) SERVER_USER="$OPTARG" ;; p) PROJECT_NAME="$OPTARG" ;; c) CONTAINER_NAME="$OPTARG" ;; v) VERSION="$OPTARG" ;; h) echo "用法: $0 [选项]" echo "选项:" echo " -i IP地址 服务器IP地址 (默认: 139.155.109.62)" echo " -u 用户名 SSH用户名 (默认: root)" echo " -p 项目名 项目名称 (默认: novalon-website)" echo " -c 容器名 容器名称 (默认: novalon-website)" echo " -v 版本号 版本号 (默认: 1.0.0)" echo " -h 显示帮助信息" exit 0 ;; \?) echo "无效选项: -$OPTARG" >&2 exit 1 ;; esac done PROJECT_DIR="$DEPLOY_ROOT/$PROJECT_NAME" LOG_DIR="./logs" LOG_FILE="$LOG_DIR/deploy_$(date +%Y%m%d_%H%M%S).log" mkdir -p "$LOG_DIR" exec > >(tee -a "$LOG_FILE") 2>&1 echo "🚀 开始部署Novalon网站到服务器 $SERVER_IP" echo "📁 部署根目录: $DEPLOY_ROOT" echo "📁 项目目录: $PROJECT_DIR" echo "🐳 容器名称: $CONTAINER_NAME" echo "📦 版本号: $VERSION" echo "📋 部署日志: $LOG_FILE" echo "" echo "📋 步骤0: 部署前检查..." for file in docker-compose.yml Dockerfile nginx-static.conf .env.example setup-ssl.sh; do if [ ! -f "$file" ]; then echo "❌ 缺少必要文件: $file" exit 1 fi done if ! command -v docker-compose &> /dev/null; then echo "❌ 本地docker-compose不可用" exit 1 fi echo "✅ 部署前检查通过" echo "" echo "📋 步骤1: 验证SSH连接..." if ! ssh -o ConnectTimeout=5 "$SERVER_USER@$SERVER_IP" exit; then echo "❌ 无法连接到服务器 $SERVER_IP" exit 1 fi if ! ssh "$SERVER_USER@$SERVER_IP" "docker --version"; then echo "❌ 服务器上Docker不可用" exit 1 fi echo "✅ SSH连接验证成功" echo "" echo "📋 步骤2: 上传部署文件..." ssh "$SERVER_USER@$SERVER_IP" "mkdir -p '$PROJECT_DIR'" scp -r docker-compose.yml Dockerfile nginx-static.conf .env.example setup-ssl.sh "$SERVER_USER@$SERVER_IP:$PROJECT_DIR/" echo "✅ 部署文件已上传" echo "" echo "📋 步骤3: 在服务器上执行部署..." ssh "$SERVER_USER@$SERVER_IP" << ENDSSH cd '$PROJECT_DIR' echo "🔒 配置SSL证书..." chmod +x setup-ssl.sh ./setup-ssl.sh echo "📋 检查环境变量文件..." if [ ! -f .env ]; then echo "📝 创建.env文件..." cp .env.example .env echo "⚠️ 请编辑.env文件,填入正确的环境变量" echo "⚠️ 可选配置: NEXT_PUBLIC_GA_ID" fi echo "🐳 启动Docker容器..." docker-compose down docker-compose build --no-cache docker-compose up -d echo "📋 等待服务启动..." timeout=60 elapsed=0 check_interval=3 while [ $elapsed -lt $timeout ]; do if docker inspect --format='{{.State.Status}}' "$CONTAINER_NAME" 2>/dev/null | grep -q "running"; then if curl -f -s -o /dev/null "http://localhost:80" --max-time 5 2>/dev/null; then echo "✅ 服务已启动并响应正常" break else echo "⏳ 容器运行中,等待服务响应..." fi else echo "⏳ 等待容器启动..." fi sleep $check_interval elapsed=$((elapsed + check_interval)) done if [ $elapsed -ge $timeout ]; then echo "❌ 服务启动超时" echo "📋 当前容器状态:" docker ps -a | grep "$CONTAINER_NAME" echo "📋 容器日志:" docker logs "$CONTAINER_NAME" --tail 20 exit 1 fi echo "📋 检查容器状态..." docker ps | grep "$CONTAINER_NAME" echo "📋 检查容器日志..." if docker logs "$CONTAINER_NAME" --tail 50 2>/dev/null; then echo "✅ 容器日志检查完成" else echo "⚠️ 容器日志为空或无法访问" fi echo "📋 配置SSL证书自动续期..." if ! crontab -l | grep -q "certbot renew"; then if ! (crontab -l 2>/dev/null; echo "0 0,12 * * * certbot renew --quiet --post-hook 'docker restart $NGINX_CONTAINER_NAME'") | crontab -; then echo "❌ SSL证书自动续期任务配置失败" exit 1 fi echo "✅ SSL证书自动续期任务已配置" else echo "✅ SSL证书自动续期任务已存在" fi echo "✅ 部署完成!" ENDSSH echo "" echo "📋 步骤4: 部署后验证..." if ! ssh "$SERVER_USER@$SERVER_IP" "docker ps | grep -q '$CONTAINER_NAME'"; then echo "❌ 容器未运行" exit 1 fi if ! curl -f -s -o /dev/null "http://$SERVER_IP" --max-time 10; then echo "⚠️ HTTP服务响应异常" else echo "✅ HTTP服务正常" fi if ! curl -f -s -o /dev/null "https://$SERVER_IP" --max-time 10; then echo "⚠️ HTTPS服务响应异常" else echo "✅ HTTPS服务正常" fi echo "✅ 部署后验证通过" echo "" echo "🎉 部署脚本执行完成!" echo "📋 访问地址:" echo " HTTP: http://$SERVER_IP" echo " HTTPS: https://$SERVER_IP" echo " 域名: https://novalon.cn" echo "" echo "📋 后续步骤:" echo " 1. 验证网站可访问性" echo " 2. 检查容器运行状态: docker ps" echo " 3. 查看容器日志: docker logs $CONTAINER_NAME" echo " 4. 验证HTTPS配置" echo " 5. 测试网站主要功能" echo " 6. 检查SSL证书自动续期: crontab -l"