07. 第一次完整上线

1. 本章目标

前面的章节分别完成了数据库、域名、证书、PM2 和 Nginx。本章把它们整理成第一次上线的顺序清单。不要跳过中间验证;这样失败时能立即知道是哪一层的问题。

2. 上线前条件

3. 获取代码

若目录还不存在:

sudo mkdir -p /var/www/airport-operations-explorer
sudo chown deploy:deploy /var/www/airport-operations-explorer
git clone <仓库URL> /var/www/airport-operations-explorer
cd /var/www/airport-operations-explorer

确认分支与提交:

git status --short --branch
git rev-parse HEAD

服务器工作区应保持干净。不要在服务器直接修改受 Git 管理的代码;否则下次更新会出现冲突,而且修改无法通过本地测试和代码审查。

4. 创建生产环境变量

cp .env.example server/.env
chmod 600 server/.env

填写:

NODE_ENV=production
HOST=127.0.0.1
PORT=3000
CLIENT_ORIGIN=https://airport.cxhair.cn
LOG_LEVEL=info
DB_HOST=127.0.0.1
DB_PORT=3306
DB_NAME=airportdb_training
DB_USER=airport_app
DB_PASSWORD=<强随机密码>
DB_POOL_MAX=10
DB_HEALTH_TIMEOUT_MS=2000

确认没有被 Git 跟踪:

git status --short
git check-ignore -v server/.env

5. 安装、检查和构建

npm ci
npm run check

根目录 npm run check 会依次执行类型检查、测试和前后端构建。任何一步失败都停止上线。不要在服务器用 --force 跳过依赖或类型错误。

确认产物:

test -f server/dist/server.js
test -f client/dist/index.html

6. 前台验证后端

cd server
NODE_ENV=production node dist/server.js

另一个会话:

curl -i http://127.0.0.1:3000/health

预期 HTTP 200、应用状态 ok、数据库状态 up。确认后按 Ctrl+C。

这一步把“代码或环境变量问题”与“PM2 配置问题”分开。如果前台都不能运行,不要进入 PM2。

7. 启动 PM2

在仓库根目录准备第 5 章的 ecosystem.config.cjs,然后:

cd /var/www/airport-operations-explorer
pm2 start ecosystem.config.cjs
pm2 status
curl -i http://127.0.0.1:3000/health
pm2 save

首次部署还要执行 pm2 startup 输出的 systemd 命令。

8. 配置 Nginx

安装第 6 章的配置:

sudo nginx -t
sudo systemctl reload nginx

如果证书尚未申请,先使用纯 HTTP server 完成 Certbot 验证,再由 Certbot 安装证书或手工合并 HTTPS 配置。

9. 从外到内验证

DNS

dig +short airport.cxhair.cn A

HTTPS 和证书

curl -I https://airport.cxhair.cn/

SPA 页面

curl -I https://airport.cxhair.cn/flights

API 与数据库

curl -i https://airport.cxhair.cn/health

监听范围

sudo ss -lntp | grep -E ':80|:443|:3000|:3306'

3000 和 3306 应绑定到回环地址或预期私有地址,不应为公网的 0.0.0.0。

进程与日志

pm2 status
pm2 logs airport-api --lines 100
sudo tail -n 100 /var/log/nginx/airport.error.log

10. 浏览器冒烟测试

用浏览器完成:

  1. 打开首页;
  2. 刷新 /flights 等前端路由;
  3. 查看开发者工具 Network;
  4. 确认接口请求使用 https://airport.cxhair.cn/... 同源地址;
  5. 确认没有 Mixed Content 或 CORS 错误;
  6. 确认健康状态能显示 API 与数据库情况。

如果前端仍请求 localhost:3000,说明代码硬编码了开发地址。生产前端必须使用相对路径。

11. 发布记录

至少记录:

发布时间:
Git commit:
Node.js 版本:
MySQL 版本:
Nginx 版本:
PM2 版本:
数据库 schema:
健康检查结果:
执行人:

不要在记录中写数据库密码或私钥路径内容。

12. 本章验收

下一章:日常更新与回滚