Node.js项目云服务器部署全攻略:从零到生产环境实战指南

一、部署前的基础准备

1.1 云服务器选型与配置

选择云服务器时需综合考虑项目规模、并发量和预算。对于中小型Node.js应用,推荐配置为:2核CPU、4GB内存、50GB SSD存储,带宽根据预期流量选择(建议初期3-5Mbps)。操作系统建议选择Ubuntu 22.04 LTS或CentOS 8,这两个系统对Node.js有完善的社区支持。

1.2 服务器安全加固

部署前必须完成基础安全配置:

  • 修改默认SSH端口(如从22改为2222)
  • 禁用root用户远程登录
  • 配置SSH密钥认证
  • 安装fail2ban防止暴力破解
  • 配置防火墙规则(仅开放80/443/2222等必要端口)

示例防火墙配置(Ubuntu):

  1. sudo ufw default deny incoming
  2. sudo ufw default allow outgoing
  3. sudo ufw allow 2222/tcp
  4. sudo ufw allow 80/tcp
  5. sudo ufw allow 443/tcp
  6. sudo ufw enable

1.3 开发环境同步

确保本地开发环境与生产环境一致:

  • Node.js版本(建议使用nvm管理多版本)
  • npm/yarn版本
  • 项目依赖版本(通过package-lock.json锁定)

二、Node.js环境部署

2.1 Node.js安装

推荐使用nvm安装Node.js,便于版本切换:

  1. curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
  2. source ~/.bashrc
  3. nvm install --lts
  4. nvm use --lts

2.2 项目文件传输

推荐使用rsync进行文件同步,比scp更高效:

  1. rsync -avz --exclude='node_modules/' --exclude='.env' \
  2. /local/project/path/ \
  3. username@server_ip:/remote/project/path/

2.3 环境变量配置

使用.env文件管理环境变量(需添加到.gitignore):

  1. DB_HOST=localhost
  2. DB_PORT=5432
  3. JWT_SECRET=your_secret_key

在项目中通过dotenv加载:

  1. require('dotenv').config();
  2. console.log(process.env.DB_HOST);

三、进程管理与持久化

3.1 PM2进程管理

PM2是Node.js最流行的进程管理器,提供:

  • 进程守护
  • 自动重启
  • 负载均衡
  • 日志管理

安装与基本使用:

  1. npm install pm2 -g
  2. pm2 start app.js --name "my-app"
  3. pm2 save # 保存进程列表
  4. pm2 startup # 生成开机启动脚本

生产环境推荐配置:

  1. // ecosystem.config.js
  2. module.exports = {
  3. apps: [{
  4. name: "my-app",
  5. script: "app.js",
  6. instances: "max", // 或指定具体数量
  7. exec_mode: "cluster",
  8. env: {
  9. NODE_ENV: "production"
  10. },
  11. error_file: "/var/log/my-app-err.log",
  12. out_file: "/var/log/my-app-out.log"
  13. }]
  14. };

3.2 日志管理方案

推荐使用winston+PM2日志系统组合:

  1. const winston = require('winston');
  2. const { combine, timestamp, printf } = winston.format;
  3. const logFormat = printf(({ level, message, timestamp }) => {
  4. return `${timestamp} ${level}: ${message}`;
  5. });
  6. const logger = winston.createLogger({
  7. level: 'info',
  8. format: combine(
  9. timestamp(),
  10. logFormat
  11. ),
  12. transports: [
  13. new winston.transports.File({ filename: 'combined.log' }),
  14. new winston.transports.Console()
  15. ]
  16. });
  17. module.exports = logger;

四、Nginx反向代理配置

4.1 基本代理设置

配置Nginx处理静态文件和反向代理:

  1. server {
  2. listen 80;
  3. server_name example.com;
  4. location / {
  5. proxy_pass http://localhost:3000;
  6. proxy_http_version 1.1;
  7. proxy_set_header Upgrade $http_upgrade;
  8. proxy_set_header Connection 'upgrade';
  9. proxy_set_header Host $host;
  10. proxy_cache_bypass $http_upgrade;
  11. }
  12. location /static/ {
  13. alias /var/www/my-app/static/;
  14. expires 30d;
  15. }
  16. }

4.2 HTTPS配置

使用Let’s Encrypt免费证书:

  1. sudo apt install certbot python3-certbot-nginx
  2. sudo certbot --nginx -d example.com -d www.example.com

自动续期配置:

  1. sudo certbot renew --dry-run
  2. # 添加到crontab每月检查
  3. 0 3 * * * /usr/bin/certbot renew --quiet

五、自动化部署方案

5.1 Git Hook自动部署

创建服务器端裸仓库:

  1. mkdir -p /var/repo/my-app.git
  2. cd /var/repo/my-app.git
  3. git init --bare

配置post-receive钩子:

  1. cat > hooks/post-receive <<EOF
  2. #!/bin/bash
  3. TARGET="/var/www/my-app"
  4. GIT_DIR="/var/repo/my-app.git"
  5. BRANCH="master"
  6. while read oldrev newrev ref
  7. do
  8. branch=`echo $ref | cut -d'/' -f3`
  9. if [ "$branch" = "$BRANCH" ]; then
  10. echo "Ref $ref received. Deploying ${branch} to production..."
  11. git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $branch
  12. cd $TARGET
  13. npm install --production
  14. pm2 reload my-app
  15. else
  16. echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
  17. fi
  18. done
  19. EOF
  20. chmod +x hooks/post-receive

5.2 CI/CD集成方案

推荐使用GitHub Actions示例配置:

  1. name: Deploy Node.js App
  2. on:
  3. push:
  4. branches: [ main ]
  5. jobs:
  6. deploy:
  7. runs-on: ubuntu-latest
  8. steps:
  9. - uses: actions/checkout@v2
  10. - name: Install Node.js
  11. uses: actions/setup-node@v2
  12. with:
  13. node-version: '16'
  14. - name: Install dependencies
  15. run: npm ci
  16. - name: Deploy to Server
  17. uses: appleboy/ssh-action@master
  18. with:
  19. host: ${{ secrets.SERVER_IP }}
  20. username: ${{ secrets.SERVER_USER }}
  21. key: ${{ secrets.SSH_PRIVATE_KEY }}
  22. script: |
  23. cd /var/www/my-app
  24. git pull origin main
  25. npm ci --production
  26. pm2 reload my-app

六、常见问题解决方案

6.1 端口占用问题

查找并终止占用端口的进程:

  1. sudo lsof -i :3000
  2. sudo kill -9 <PID>

6.2 内存泄漏排查

使用PM2内存监控:

  1. pm2 monit

或生成堆快照分析:

  1. # 安装诊断工具
  2. npm install -g node-heapdump
  3. # 在代码中添加
  4. const heapdump = require('heapdump');
  5. app.get('/dump', (req, res) => {
  6. const filename = `/tmp/heapdump-${Date.now()}.heapsnapshot`;
  7. heapdump.writeSnapshot(filename, (err) => {
  8. if (err) return res.status(500).send('Error creating dump');
  9. res.download(filename);
  10. });
  11. });

6.3 性能优化建议

  1. 启用Gzip压缩(Nginx配置):

    1. gzip on;
    2. gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
  2. 启用HTTP/2(需HTTPS):

    1. listen 443 ssl http2;
  3. 使用CDN加速静态资源

七、监控与维护

7.1 基础监控指标

推荐监控项:

  • CPU使用率
  • 内存使用量
  • 响应时间(P90/P99)
  • 错误率
  • 请求量

7.2 告警配置示例

使用PM2的邮件告警:

  1. pm2 set pm2:email your@email.com
  2. pm2 set pm2:smtp_host smtp.example.com
  3. pm2 set pm2:smtp_port 587
  4. pm2 set pm2:smtp_user user
  5. pm2 set pm2:smtp_password pass

或在ecosystem.config.js中配置:

  1. module.exports = {
  2. apps: [{
  3. // ...其他配置
  4. pm2_env: {
  5. EMAIL: "your@email.com",
  6. SMTP_HOST: "smtp.example.com"
  7. }
  8. }]
  9. };

通过以上系统化的部署方案,开发者可以构建出稳定、高效、安全的Node.js生产环境。实际部署时建议先在测试环境验证所有流程,再逐步迁移到生产环境。定期回顾和优化部署流程,能够持续提升应用的可靠性和运维效率。