14 KiB
Next.js 项目基于 GitHub Webhook 与宝塔面板的自动化部署流程文档
I. 概述
本流程文档详细介绍了如何通过 GitHub 的 Webhook 功能与宝塔面板相结合,实现 Next.js 项目代码的自动化部署。当您向 GitHub 仓库提交代码后,服务器将自动拉取最新代码、安装依赖、构建项目并重启应用,从而实现持续集成与部署(CI/CD),极大地提升开发效率和部署的可靠性。
核心理念: 一次性配置宝塔面板的基础环境和网站,后续代码更新通过 GitHub Webhook 触发宝塔面板执行自动化部署脚本。
II. 前提条件
在开始配置之前,请确保您已具备以下条件:
- GitHub 账号:并已拥有一个托管 Next.js 项目代码的仓库。
- 宝塔面板服务器:一台已安装宝塔面板的 Linux 服务器。
- 已安装环境:服务器上已通过宝塔面板的软件商店安装了 Nginx (或 Apache)、Node.js (推荐 LTS 版本) 和 PM2 管理器。
- Git 环境:服务器上已安装 Git(通常宝塔面板会自带或可通过软件商店安装)。
- 域名解析:您的域名已正确解析到宝塔面板服务器的 IP 地址。
III. 整体部署流程概览
以下是整个自动化部署流程的高层概览图:
```mermaid
graph TD
A[开发者 Push 代码到 GitHub 仓库] --> B(GitHub 仓库);
B -- 代码更新 --> C{GitHub Webhook 触发};
C -- Payload URL & Secret --> D[宝塔面板服务器];
D -- 执行 deploy_webhook.php 脚本 --> E[自动部署脚本:
git pull
npm install
npm run build
pm2 restart];
E --> F[Next.js 应用更新并重启];
F --> G[用户通过域名访问最新网站];
```
IV. 各环节详细流程与配置
A. 阶段一:开发者本地代码提交与推送
这是您日常开发的工作流程。
```mermaid graph TD A[开发者本地修改 Next.js 代码] --> B[git add]; B --> C[git commit -m "更新了新功能"]; C --> D[git push origin main]; D --> E(代码推送到 GitHub 远程仓库); ```
操作说明:
您在本地完成 Next.js 项目开发后,通过标准的 Git 命令将代码提交并推送到 GitHub 仓库的指定分支(例如 main 或 master)。
B. 阶段二:宝塔面板服务器环境与网站配置(由您手动完成,一次性)
这是实现自动化部署的基础,需要您在宝塔面板上进行一次性设置。
-
登录宝塔面板。
-
安装 Node.js 和 PM2 管理器:
- 在宝塔面板左侧菜单选择
软件商店。 - 搜索并安装
Node.js(推荐安装 LTS 版本,例如 16.x, 18.x, 20.x)。 - 搜索并安装
PM2 管理器。PM2 是 Node.js 应用程序的生产级进程管理器,能确保您的 Next.js 应用在服务器上持续运行,并在代码更新后平滑重启。
- 在宝塔面板左侧菜单选择
-
创建网站与域名:
- 在宝塔面板左侧菜单选择
网站->添加站点。 - 填写您的域名(根据截图推测,可能是
touzhi.quwanzhi.com或您实际绑定的域名)。 FTP和数据库可以选择不创建(如果您的 Next.js 项目是纯前端或后端分离的)。PHP 版本选择纯静态。网站目录:根据截图,您的项目可能在/www/wwwroot/tongzhi。请确认并记住这个目录。 稍后它将是您的 Git 仓库克隆和deploy_webhook.php脚本存放的目录。- 点击
提交。
- 在宝塔面板左侧菜单选择
-
配置 Nginx 反向代理 Next.js 应用: Next.js 应用通常运行在 Node.js 服务器上,并通过 Nginx 进行反向代理实现外网访问。
- 在宝塔面板
网站列表中,找到您刚刚创建的网站,点击右侧的设置。 - 切换到
配置文件选项卡。 - 在
server配置块中,添加以下location配置(请将3000替换为 Next.js 应用实际监听的端口): ```nginxNginx 配置示例 (添加到 server 段内)
location / { proxy_pass http://127.0.0.1:3000; # <--- 替换为 PM2 启动的 Next.js 应用监听的实际端口 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; # 如果您的 Next.js 应用有特殊路由需求,可能需要添加其他配置 } ``` - 点击
保存。
- 在宝塔面板
-
使用 PM2 管理 Next.js 应用:
- 在宝塔面板左侧菜单选择
PM2管理器。 - 点击
添加项目。 项目目录:选择您的网站根目录(根据截图可能是/www/wwwroot/tongzhi)。启动文件:填写node_modules/next/dist/bin/next。项目名称:根据截图,您的 PM2 项目名称可能是tongzhi(请务必记住这个名称,稍后在 Webhook 脚本中会用到)。启动参数:填写start -p 3000(这里的3000是您的 Next.js 应用监听的端口,请与 Nginx 反向代理中的端口保持一致)。- 点击
提交。 - PM2 会自动启动您的 Next.js 应用。您可以点击
日志查看应用启动情况。
- 在宝塔面板左侧菜单选择
-
配置 Git 部署: 宝塔面板内置的 Git 部署功能是接收 GitHub Webhook 通知并触发部署脚本的关键。
- 在宝塔面板
网站列表中,找到对应的网站,点击右侧的设置。 - 在网站设置窗口中,找到
Git选项卡,点击进入。 - 勾选
启用Git部署。 平台选择Github。项目地址:填写您的 GitHub 仓库的 HTTPS 地址。例如:https://github.com/fnvtk/wztouzhi.git。分支:填写您希望自动部署的分支名称,通常是main或master。Token:设置一个随机且复杂的字符串作为密钥,例如your_custom_deploy_secret_wztouzhi_bt。请务必牢记这个密钥,稍后在 GitHub Webhook 配置和部署脚本中会用到。项目部署目录:宝塔会自动填写网站的根目录(例如/www/wwwroot/tongzhi),请确保它是您项目代码实际要部署的路径。部署类型:选择拉取。- 重要:
部署完成后执行的命令:这里暂时留空,您将在后续步骤中将我为您生成的脚本内容粘贴到此处。 - 获取 WebHook 地址: 配置完上述信息并点击
保存后,宝塔面板会为您生成一个WebHook地址。复制这个 URL!
- 在宝塔面板
C. 阶段三:GitHub 仓库 Webhook 配置(由您手动完成,一次性)
这个配置将使得 GitHub 在您推送代码时通知宝塔面板。
```mermaid graph TD A[登录 GitHub 仓库] --> B[Settings]; B --> C[Webhooks]; C --> D[Add webhook]; D --> E[填写 Payload URL]; E --> F[设置 Secret]; F --> G[选择 'Just the push event']; G --> H[Add webhook]; H --> I(Webhook 配置完成); ```
操作说明:
- 登录 GitHub,进入您的
wztouzhi项目仓库。 - 点击仓库顶部的
Settings(设置)。 - 在左侧导航栏中,点击
Webhooks。 - 点击
Add webhook(添加 Webhook)。 - 填写以下信息:
- Payload URL:粘贴您在宝塔面板 Git 部署设置中复制的
WebHook地址。 - Content type:选择
application/json。 - Secret (可选,但强烈推荐):粘贴您在宝塔面板 Git 部署中设置的
Token(那个强密码)。 - Which events would you like to trigger this webhook?:选择
Just the push event.(仅推送事件)。 Active:确保此选项被勾选。
- Payload URL:粘贴您在宝塔面板 Git 部署设置中复制的
- 点击
Add webhook完成添加。
D. 阶段四:自动化部署脚本 deploy_webhook.php (由我提供,您粘贴到宝塔)
为了实现自动化构建和重启 Next.js 应用,我们需要一个 PHP 脚本来作为宝塔面板 Git 部署的"部署完成后执行的命令"。
我为您生成了以下 deploy_webhook.php 脚本。您需要将此脚本的内容复制,并粘贴到宝塔面板网站设置中 Git 部署的"部署完成后执行的命令"文本框内。
脚本内容(已根据您的截图信息优化,请务必根据您的实际情况修改 SECRET):
```php
<?php // deploy_webhook.php // GitHub Webhook for Next.js (React) project deployment on Baota Panel // --- 安全配置 --- // 建议在宝塔面板的环境变量中设置此密钥,或者从配置文件读取,避免直接硬编码 $SECRET = 'your_deploy_secret_wztouzhi_bt'; // **请替换为你在宝塔面板Git部署中设置的Token** $PROJECT_ROOT = '/www/wwwroot/tongzhi'; // **已根据截图更新为 `/www/wwwroot/tongzhi`** $LOG_FILE = $PROJECT_ROOT . '/deploy.log'; // 部署日志文件,用于记录部署过程 // --- 函数定义 --- function log_message($message) { global $LOG_FILE; file_put_contents($LOG_FILE, date('[Y-m-d H:i:s]') . ' ' . $message . PHP_EOL, FILE_APPEND); } function verify_signature($payload, $signature, $secret) { $hash = 'sha1=' . hash_hmac('sha1', $payload, $secret); return hash_equals($signature, $hash); } // --- 请求处理 --- log_message('Webhook triggered.'); // 获取 GitHub 请求头 $github_signature = $_SERVER['HTTP_X_HUB_SIGNATURE'] ?? ''; $github_event = $_SERVER['HTTP_X_GITHUB_EVENT'] ?? ''; $payload = file_get_contents('php://input'); // 验证 Secret if (empty($github_signature) || !verify_signature($payload, $github_signature, $SECRET)) { log_message('Invalid signature. Aborting deployment.'); http_response_code(401); die('Invalid signature'); } log_message("GitHub Event: {$github_event}"); // 只处理 push 事件 if ($github_event === 'push') { log_message('Processing push event...'); // 切换到项目根目录 chdir($PROJECT_ROOT); log_message("Changed directory to: " . getcwd()); // 执行 Git Pull log_message('Executing git pull...'); $output = shell_exec('git pull 2>&1'); log_message("Git Pull Output:\n" . $output); // 检查 Next.js 项目文件 (package.json) if (file_exists('package.json')) { log_message('Detected Next.js project. Installing dependencies and building...'); // 安装 Node.js 依赖 log_message('Executing npm install...'); // 使用 --force 强制安装,避免因包版本冲突导致安装失败 $output = shell_exec('npm install --force 2>&1'); log_message("npm install Output:\n" . $output); // 构建 Next.js 项目 log_message('Executing npm run build...'); $output = shell_exec('npm run build 2>&1'); log_message("npm run build Output:\n" . $output); // 重启 PM2 进程 (已根据截图更新应用名为 'tongzhi') $PM2_APP_NAME = 'tongzhi'; // **已根据截图更新:请替换为你在PM2管理器中设置的项目名称** log_message("Restarting PM2 process '{$PM2_APP_NAME}'..."); $output = shell_exec("pm2 restart {$PM2_APP_NAME} 2>&1"); log_message("PM2 Restart Output:\n" . $output); } else { log_message('No package.json found. Skipping Node.js specific commands.'); } log_message('Deployment completed.'); echo 'Deployment successful!'; } else { log_message('Event not supported. Only "push" events are processed.'); echo 'Event not supported.'; } http_response_code(200); ?>```
脚本流程图:
```mermaid graph TD A[GitHub Webhook 请求] --> B{deploy_webhook.php 接收}; B -- 获取 Payload & Headers --> C{验证 Secret}; C -- 签名不匹配 --> D[401 Unauthorised]; C -- 签名匹配 --> E{事件类型为 Push?}; E -- 否 --> F[跳过,不处理]; E -- 是 --> G[切换到项目根目录]; G --> H[执行 git pull]; H --> I{检查 package.json 存在?}; I -- 否 --> J[跳过 Node.js 命令]; I -- 是 --> K[执行 npm install]; K --> L[执行 npm run build]; L --> M[执行 pm2 restart 应用名]; M --> N(部署成功,返回 200 OK); ```
V. 自动化部署完成与验证
完成以上所有配置后,每次您向 GitHub 仓库的指定分支推送代码,就会自动触发部署流程:
- GitHub 发送 Webhook 请求到宝塔面板。
- 宝塔面板接收请求并执行
deploy_webhook.php脚本。 - 脚本在服务器上拉取最新代码,安装/更新 Node.js 依赖,构建 Next.js 项目。
- PM2 自动重启您的 Next.js 应用。
- 您的网站内容更新,并能通过您绑定的域名在外网访问到最新版本。
验证方法:
- 查看 GitHub Webhook 记录: 在 GitHub 仓库的 Webhook 设置页面,查看
Recent Deliveries,确保每次推送都有成功的绿色勾选。 - 查看宝塔面板 Git 部署日志: 在宝塔面板网站设置的
Git选项卡中,通常会有部署日志,可以查看详细的执行情况。 - 查看
deploy.log文件: 脚本会在项目根目录生成deploy.log文件,记录每次部署的详细信息,方便排查问题。 - 访问您的网站: 通过域名访问您的网站,确认内容是否已更新到最新。
VI. 注意事项与优化
- 安全性:
Secret密钥是关键,请妥善保管,不要泄露。 - 权限问题:确保宝塔面板运行的用户(通常是
www用户)对项目目录有足够的读写权限,以便git pull、npm install、npm run build等命令能够正常执行。 - 依赖缓存:在部署脚本中,
npm install会在每次部署时运行。如果您的项目依赖较多,可以考虑在Dockerfile中构建一个包含依赖的镜像,或者在服务器上对node_modules进行缓存处理,以加快部署速度(此文档以直接安装为默认)。 - 错误处理:脚本中已加入了日志记录,您可以通过查看
deploy.log文件来排查部署失败的原因。 - 生产模式:确保您的 Next.js 应用在
npm run build后是以生产模式构建的。 - 持续学习:自动化部署是一个持续优化的过程,您可以根据项目需求和服务器性能,不断调整部署脚本。