后端代码部署到服务器,服务器配置数据库,pm2进程管理发布(四)
前置系列文章
从零开始:在阿里云 Ubuntu 服务器部署 Node+Express 接口(一)
阿里云域名解析 + Nginx 反向代理 + HTTPS 全流程:从 IP 访问到加密域名的完整配置(二)
将代码和数据库发布到阿里云轻量服务器(Ubuntu)的核心流程是:本地准备 → 服务器环境配置 → 代码部署(含安全传输配置文件) → 数据库迁移 → 启动服务。以下是循序渐进的详细步骤,重点解决 .env.production 不提交到 Git 的问题:
一、本地准备工作(确保代码可部署)
1. 检查本地代码规范
-
确认
.gitignore配置:确保已忽略敏感文件,避免提交到 Git:
# 项目根目录的 .gitignore 文件必须包含以下内容
.env.development
.env.production
.env.test
node_modules/
2. 导出本地数据库结构(用于服务器初始化)
在mysql workBench中到出本地数据库mydb,只需要导出数据结构,会有一个sql文件导到本地,可以自己命名,我的叫my_db.sql
二、服务器环境准备(阿里云 Ubuntu)
1. 登录服务器
通过终端登录阿里云轻量服务器(替换为你的服务器公网 IP):
ssh root@你的服务器公网IP # 例如:ssh root@120.78.xxx.xxx
输入服务器登录密码
2. 安装必要软件
如果服务器未安装以下软件,依次执行:
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装 Node.js(推荐 v16+)
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt install -y nodejs
# 安装 MySQL 服务器(生产环境数据库)
sudo apt install -y mysql-server
# 安装 PM2(Node 服务进程管理工具)
sudo npm install pm2 -g
# 安装 Nginx(反向代理、静态资源服务)
sudo apt install -y nginx
3. 配置服务器 MySQL(生产环境数据库)
步骤一:初始化 MySQL 并创建生产数据库
# 登录MySQL(Ubuntu初始无密码,直接回车)
sudo mysql -u root -p
# 设置root密码(自定义强密码,如Server@Mysql2024)
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的root密码';
FLUSH PRIVILEGES;
# 创建生产数据库(与项目.env.production一致,mydb_prod是数据库名)
CREATE DATABASE mydb_prod CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# 创建数据库专用用户(避免root直接操作)
CREATE USER 'prod_user'@'%' IDENTIFIED BY 'Prod@2024';
# 授予用户数据库权限
GRANT ALL PRIVILEGES ON mydb_prod.* TO 'prod_user'@'%';
# 刷新权限
FLUSH PRIVILEGES;
# 退出MySQL
EXIT;
.env.production如下
# 环境标识
NODE_ENV=production
# 数据库配置(服务器数据库信息,变量名与开发环境完全一致)
NODE_ENV=production
DB_HOST=localhost # 服务器数据库在本地,填localhost
DB_PORT=3306
DB_USER=prod_user # 步骤3创建的专用用户
DB_PASSWORD=Prod@2024 # 专用用户的密码
DB_NAME=mydb_prod # 生产数据库名
API_PORT=3000 # 后端服务端口
因为这个文件不能提交到git,所以要在服务器这个项目的根目录创建这个文件,并把上面的内容写进去就行。 我的是放在/root/projects/node-api-test下
步骤2: 导入本地表结构到服务器数据库
# 1. 在 Mac 终端另开窗口,上传本地 my_db.sql 到服务器的 /tmp 目录
scp /本地路径/my_db.sql root@你的服务器IP:/tmp/
# 例如:scp ~/project/my_db.sql root@120.78.xxx.xxx:/tmp/
# 2. 回到服务器终端,导入表结构到 mydb_prod 数据库
mysql -u root -p mydb_prod < /tmp/my_db.sql
# 输入服务器 MySQL 的 root 密码(步骤1中设置的),完成后表结构导入成功
服务器生产数据库中创建 users 表(表结构迁移)
在生产环境部署中,需将本地开发的 users 表结构迁移到服务器的 mydb_prod 数据库中,确保后端接口能正常读写用户数据。
服务器导入 users 表结构到 mydb_prod
登录服务器终端,将表结构导入生产数据库:
# 服务器终端执行(输入prod_user的密码Prod@2024)
mysql -u prod_user -p mydb_prod < /tmp/my_db.sql
(4)验证表是否创建成功
登录服务器 MySQL,检查 users 表是否存在:
# 服务器终端登录MySQL
mysql -u prod_user -p mydb_prod
# 查看数据库中的表
SHOW TABLES; # 应显示 users 表
# 查看表结构(可选)
DESCRIBE users; # 显示 users 表的字段、类型等结构信息
# 退出MySQL
EXIT;
补充说明
- 若本地
users表有初始必要数据(如管理员账号),可去掉--no-data参数,导出包含数据的表结构:mysqldump -u 本地用户名 -p 本地数据库名 users > users_with_data.sql,再按相同步骤导入。 - 表结构迁移是生产部署的关键步骤,确保服务器数据库表结构与本地开发环境一致,否则会出现 “表不存在”“字段缺失” 等接口错误。
发布代码
登录服务器,cd /root/xxx/xxx 到自己的项目根目录,执行git pull ,然后执行pm2 restart node-api-test
这时候会报错,提示环境变量是undefined,process.env.NODE_ENV 打印出的永远是undefined,所以下面这段代码,发布到服务器上就挂了
const env = process.env.NODE_ENV || 'development'
const envPath = path.resolve(__dirname, `../.env.${env}`)
console.log('envPath', envPath)
// 会打印出undefined
原因分析
-
当你在服务器命令行直接输入 pm2 start app.js 时,Linux shell 并没有设置 NODE_ENV,代码里 process.env.NODE_ENV 就会变成 undefined,然后你的代码兜底逻辑将其设为 development,于是去读开发环境的配置,导致报错。
-
app.js 方式启动: 执行 pm2 start app.js 时,PM2 只是简单地执行 node app.js。除非你在操作系统层面(如 /etc/profile)设置了全局 NODE_ENV,否则它就是空的。
解决方案:
使用 ecosystem.config.cjs(最推荐,工业标准)
项目根目录创建ecosystem.config.cjs
// ecosystem.config.cjs
module.exports = {
apps: [
{
name: 'node-api-test',
script: './app.js',
instances: 1,
autorestart: true,
watch: false,
env: {
NODE_ENV: 'development',
},
env_production: {
NODE_ENV: 'production',
},
},
],
}
启动命令:
以后在服务器上启动或重启,统一使用以下命令,不要再用 pm2 start app.js:
# 首次启动(生产):
pm2 start ecosystem.config.cjs --env production
# 代码更新后重启 平滑重载(零停机):
pm2 reload ecosystem.config.cjs --env production
# 完全重启:
pm2 restart ecosystem.config.cjs --env production