You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在同级目录构建Next.js项目并实现零停机部署?

独立目录构建+无停机部署方案优化

问题描述

希望在现有仓库的同级目录中构建项目,避免构建失败导致目录混乱。理想流程是在独立目录完成构建,成功后将文件移至运行目录并重启PM2,同时保证服务无停机。当前使用的GitHub Actions部署配置如下:

name: Staging Deploy

on:
  push:
    branches: [ "main" ]

jobs:
  build:

    runs-on: Staging
    environment: Staging

    strategy:
      matrix:
        node-version: [16.x]
        # See supported Node.js release schedule at https://nodejs.org/en/about/releases/

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    - run: npm install
    - name: Create env file
      run: |
        touch .env
        ...create env file with repo secrets
    - run: npm run build --if-present
    - name: Restart PM2
      id: restart_pm2
      run: pm2 reload reponame
      continue-on-error: true
    - name: Start PM2
      if: steps.restart_pm2.outcome != 'success'
      run: pm2 start pm2.config.js

解决方案

1. 独立构建目录配置

在GitHub Actions中通过指定working-directory设置独立构建目录,建议将其设为现有仓库的同级目录(比如现有仓库路径为/home/user/repo,构建目录设为/home/user/repo-build),构建前先创建并清空该目录,避免残留旧文件。

2. 原子替换避免目录混乱

构建成功后用原子操作替换运行目录,避免中途失败导致目录损坏:

  • 先将构建好的产物临时重命名
  • 对原运行目录做备份(可选)
  • 用mv完成原子替换(同一文件系统下mv是原子操作,不会出现中间损坏状态)

3. PM2无停机重载保障

PM2的reload命令本身支持无停机重启,替换运行目录后执行pm2 reload --update-env,确保进程加载新目录下的文件;如果进程不存在则自动启动。

4. 完整优化后的GitHub Actions配置

name: Staging Deploy

on:
  push:
    branches: [ "main" ]

jobs:
  build-and-deploy:
    runs-on: Staging
    environment: Staging
    strategy:
      matrix:
        node-version: [16.x]

    steps:
    - name: 创建并清空独立构建目录
      run: |
        # 自定义构建目录路径(与现有仓库同级)
        BUILD_DIR="/home/user/repo-build"
        RUN_DIR="/home/user/repo-run"
        mkdir -p $BUILD_DIR
        rm -rf $BUILD_DIR/*

    - uses: actions/checkout@v3
      with:
        # 将代码检出到独立构建目录
        path: /home/user/repo-build

    - name: 配置Node.js环境
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
        cache-dependency-path: /home/user/repo-build/package-lock.json

    - name: 安装依赖
      working-directory: /home/user/repo-build
      run: npm install

    - name: 创建环境变量文件
      working-directory: /home/user/repo-build
      run: |
        touch .env
        # 替换为你的环境变量写入逻辑
        # echo "API_URL=${{ secrets.API_URL }}" >> .env
        # echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> .env

    - name: 构建项目
      working-directory: /home/user/repo-build
      run: npm run build --if-present

    - name: 原子替换运行目录
      run: |
        BUILD_DIR="/home/user/repo-build"
        RUN_DIR="/home/user/repo-run"
        TEMP_DIR="/home/user/repo-run-temp"
        BACKUP_DIR="/home/user/repo-run-backup"

        # 临时重命名构建目录
        mv $BUILD_DIR $TEMP_DIR
        # 备份原运行目录(可选)
        if [ -d "$RUN_DIR" ]; then
          mv $RUN_DIR $BACKUP_DIR
        fi
        # 原子替换为新运行目录
        mv $TEMP_DIR $RUN_DIR
        # 可选:删除旧备份
        # rm -rf $BACKUP_DIR

    - name: PM2无停机重载/启动
      run: |
        # 重载进程,更新环境变量
        pm2 reload reponame --update-env
        # 如果重载失败(进程不存在),则启动新进程
        if [ $? -ne 0 ]; then
          pm2 start /home/user/repo-run/pm2.config.js --name reponame
        fi

额外建议

  • 添加构建后健康检查:调用服务的健康状态接口,确认服务正常后再完成部署流程
  • 使用PM2的ecosystem.config.js配置文件,明确指定cwd为运行目录,方便统一管理
  • 保留备份目录一段时间,出现问题可快速回滚

内容的提问来源于stack exchange,提问作者LUKER

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 00:01:06