同一VPS中两个Node.js应用.env配置串用,数据库连接错误求助
问题排查与解决方案
一、先排查核心:.env文件加载异常(最可能的根源)
你的问题是prod应用连接到dev数据库,这和Apache反向代理的端口冲突无关(代理只处理外部请求转发,不影响应用内部的数据库连接),优先从环境变量加载环节入手:
1. 验证.env文件的加载路径与优先级
- Node.js的
dotenv默认加载当前工作目录下的.env文件,PM2启动时如果未指定工作目录,可能会使用PM2的默认工作目录(而非应用目录)。- 执行
pm2 show <prod-app-name>,查看输出中的cwd字段,确认是否为prod应用的根目录;dev应用同理检查。 - 如果工作目录不对,在PM2启动时指定
--cwd参数,比如:pm2 start index.js --name prod --cwd /path/to/prod-app。
- 执行
- 检查PM2配置文件(如
ecosystem.config.js),是否存在env字段覆盖了数据库凭证——PM2配置的环境变量优先级高于.env文件。
2. 确认代码中.env的加载时机
确保require('dotenv').config()在数据库连接初始化代码之前执行,否则会导致数据库连接读取不到正确的.env变量。可以在prod代码中添加日志验证:
require('dotenv').config(); console.log('Prod DB Name:', process.env.DB_NAME); // 启动后查看日志是否为prod的数据库名
3. 排除手动启动与PM2启动的差异
手动在prod目录下执行node index.js,观察是否仍连接到dev数据库:
- 如果手动启动正常,说明是PM2的工作目录或配置问题;
- 如果手动启动也异常,检查prod目录下的
.env是否被误替换为dev的内容,或者代码中存在硬编码的数据库配置。
二、Apache反向代理与端口冲突的排查(次要但需确认)
如果两个Node应用监听同一端口,会导致后启动的应用无法绑定端口(报错EADDRINUSE),但你描述dev启动后prod仍能运行,说明端口大概率不冲突,但仍需验证:
1. 确认两个应用的监听端口
检查prod和dev的代码,确保监听端口不同:
// prod应用 app.listen(3000, () => console.log('Prod running on port 3000')); // dev应用 app.listen(3001, () => console.log('Dev running on port 3001'));
执行netstat -tulpn | grep node,查看Node进程占用的端口,确认两个应用端口无重叠。
2. 修正Apache反向代理配置
复制prod配置后必须修改代理目标端口,确保子域名对应正确的Node应用:
# prod的虚拟主机配置 <VirtualHost *:80> ServerName your-domain.com ProxyPass / http://localhost:3000/ ProxyPassReverse / http://localhost:3000/ </VirtualHost> # dev的虚拟主机配置 <VirtualHost *:80> ServerName dev.your-domain.com ProxyPass / http://localhost:3001/ ProxyPassReverse / http://localhost:3001/ </VirtualHost>
修改后重启Apache:systemctl restart apache2
三、数据库层面验证(兜底排查)
开启数据库的通用日志(如MySQL的general_log),查看prod应用进程对应的连接请求,确认是应用端传入了错误的数据库凭证,还是数据库配置本身有问题。
内容的提问来源于stack exchange,提问作者Tata Volador
相关产品推荐
相关产品推荐

