From 6c4c6c0c1fb3c26bf785b6fefe98465e4627edd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Thu, 26 Mar 2026 20:15:21 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=85=A8=E9=9D=A2=E6=94=B9?= =?UTF-8?q?=E8=BF=9B=E9=83=A8=E7=BD=B2=E8=84=9A=E6=9C=AC=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=BC=BA=E5=81=A5=E5=A3=AE=E6=80=A7=E5=92=8C=E5=8F=AF=E7=BB=B4?= =?UTF-8?q?=E6=8A=A4=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 高优先级改进: - 使用更精确的容器状态检查方法(docker inspect) - 添加容器日志命令的错误处理 - 将nginx容器名称改为变量(NGINX_CONTAINER_NAME) 中优先级改进: - 添加部署前文件检查(检查必要文件和工具) - 添加部署后验证(HTTP/HTTPS服务响应检查) - 添加日志记录功能(自动创建日志文件) - 改进健康检查机制(检查容器状态和服务响应) 低优先级改进: - 添加参数化配置(支持命令行参数) - 添加帮助信息(-h选项) 其他改进: - 更新.gitignore,忽略部署日志文件 - 支持自定义服务器IP、用户名、项目名、容器名、版本号 - 提供详细的帮助信息和使用说明 --- .gitignore | 4 +- deploy.sh | 115 ++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 109 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 454fb7c..71e9a61 100644 --- a/.gitignore +++ b/.gitignore @@ -179,10 +179,12 @@ logs/ *.log npm-debug.log* yarn-debug.log* -yarn-error.log* pnpm-debug.log* lerna-debug.log* +# Deployment logs +deploy_*.log + # IDE .idea/ .vscode/ diff --git a/deploy.sh b/deploy.sh index 88533fb..b178e34 100755 --- a/deploy.sh +++ b/deploy.sh @@ -8,19 +8,78 @@ 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 "📦 版本号: 1.0.0" +echo "📦 版本号: $VERSION" +echo "📋 部署日志: $LOG_FILE" echo "" +echo "📋 步骤0: 部署前检查..." + +for file in docker-compose.yml Dockerfile nginx.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 "" @@ -55,16 +114,29 @@ docker-compose up -d echo "📋 等待服务启动..." timeout=60 elapsed=0 +check_interval=3 + while [ $elapsed -lt $timeout ]; do - if docker ps | grep -q "$CONTAINER_NAME"; then - echo "✅ 服务已启动" - break + if docker inspect --format='{{.State.Status}}' "$CONTAINER_NAME" 2>/dev/null | grep -q "running"; then + if curl -f -s -o /dev/null "http://localhost:3000" --max-time 5 2>/dev/null; then + echo "✅ 服务已启动并响应正常" + break + else + echo "⏳ 容器运行中,等待服务响应..." + fi + else + echo "⏳ 等待容器启动..." fi - sleep 2 - elapsed=$((elapsed + 2)) + 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 @@ -72,12 +144,15 @@ echo "📋 检查容器状态..." docker ps | grep "$CONTAINER_NAME" echo "📋 检查容器日志..." -docker logs "$CONTAINER_NAME" --tail 50 +if docker logs "$CONTAINER_NAME" --tail 50 2>/dev/null; then + echo "✅ 容器日志检查完成" +else + echo "⚠️ 容器日志为空或无法访问" +fi echo "📋 配置SSL证书自动续期..." -# 添加certbot自动续期cron任务 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 novalon-nginx'") | crontab -; 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 @@ -89,6 +164,28 @@ 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 "📋 访问地址:"