部署上线 #

一、部署前准备 #

1.1 环境变量 #

.env.production:

text
NODE_ENV=production
PORT=3000
DATABASE_URL=mongodb://localhost:27017/myapp
JWT_SECRET=your-production-secret
JWT_EXPIRES_IN=7d

1.2 安全检查清单 #

  • [ ] 移除敏感信息
  • [ ] 设置环境变量
  • [ ] 启用HTTPS
  • [ ] 配置CORS
  • [ ] 设置安全头
  • [ ] 启用日志记录

二、PM2部署 #

2.1 安装PM2 #

bash
npm install pm2 -g

2.2 配置文件 #

ecosystem.config.js:

javascript
module.exports = {
    apps: [{
        name: 'my-app',
        script: './server.js',
        instances: 'max',
        exec_mode: 'cluster',
        autorestart: true,
        watch: false,
        max_memory_restart: '1G',
        env: {
            NODE_ENV: 'development'
        },
        env_production: {
            NODE_ENV: 'production'
        },
        error_file: './logs/error.log',
        out_file: './logs/out.log',
        log_date_format: 'YYYY-MM-DD HH:mm:ss'
    }]
};

2.3 启动命令 #

bash
pm2 start ecosystem.config.js --env production
pm2 save
pm2 startup

2.4 常用命令 #

bash
pm2 list
pm2 logs
pm2 monit
pm2 restart all
pm2 reload all
pm2 stop all
pm2 delete all

三、Docker部署 #

3.1 Dockerfile #

dockerfile
FROM node:18-alpine

WORKDIR /app

COPY package*.json ./

RUN npm ci --only=production

COPY . .

EXPOSE 3000

USER node

CMD ["node", "server.js"]

3.2 docker-compose.yml #

yaml
version: '3.8'

services:
    app:
        build: .
        ports:
            - "3000:3000"
        environment:
            - NODE_ENV=production
            - DATABASE_URL=mongodb://mongo:27017/myapp
        depends_on:
            - mongo
            - redis
        restart: always
    
    mongo:
        image: mongo:6
        volumes:
            - mongo_data:/data/db
        restart: always
    
    redis:
        image: redis:7-alpine
        volumes:
            - redis_data:/data
        restart: always

volumes:
    mongo_data:
    redis_data:

3.3 构建和运行 #

bash
docker-compose build
docker-compose up -d
docker-compose logs -f
docker-compose down

四、Nginx配置 #

4.1 反向代理 #

/etc/nginx/sites-available/myapp:

nginx
server {
    listen 80;
    server_name example.com www.example.com;
    
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
    
    location /static/ {
        alias /var/www/myapp/public/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

4.2 启用配置 #

bash
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

五、SSL证书 #

5.1 Let’s Encrypt #

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

5.2 自动续期 #

bash
sudo certbot renew --dry-run

六、云平台部署 #

6.1 Heroku #

Procfile:

text
web: node server.js

部署命令:

bash
heroku create my-app
heroku config:set DATABASE_URL=xxx
git push heroku main

6.2 Vercel #

vercel.json:

json
{
    "version": 2,
    "builds": [
        { "src": "server.js", "use": "@vercel/node" }
    ],
    "routes": [
        { "src": "/(.*)", "dest": "/server.js" }
    ]
}

6.3 AWS #

使用Elastic Beanstalk或EC2:

bash
eb init
eb create production
eb deploy

七、CI/CD #

7.1 GitHub Actions #

.github/workflows/deploy.yml:

yaml
name: Deploy

on:
    push:
        branches: [main]

jobs:
    deploy:
        runs-on: ubuntu-latest
        
        steps:
            - uses: actions/checkout@v3
            
            - uses: actions/setup-node@v3
              with:
                  node-version: '18'
            
            - run: npm ci
            
            - run: npm test
            
            - name: Deploy to server
              uses: appleboy/ssh-action@master
              with:
                  host: ${{ secrets.HOST }}
                  username: ${{ secrets.USERNAME }}
                  key: ${{ secrets.SSH_KEY }}
                  script: |
                      cd /var/www/myapp
                      git pull
                      npm ci --production
                      pm2 reload all

八、监控和日志 #

8.1 PM2监控 #

bash
pm2 monit
pm2 plus

8.2 日志管理 #

javascript
const winston = require('winston');

const logger = winston.createLogger({
    level: 'info',
    format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.json()
    ),
    transports: [
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});

if (process.env.NODE_ENV !== 'production') {
    logger.add(new winston.transports.Console({
        format: winston.format.simple()
    }));
}

module.exports = logger;

8.3 APM工具 #

bash
npm install newrelic

newrelic.js:

javascript
exports.config = {
    app_name: ['My App'],
    license_key: 'your-license-key',
    logging: {
        level: 'info'
    }
};

九、性能优化 #

9.1 启用压缩 #

javascript
const compression = require('compression');
app.use(compression());

9.2 静态文件缓存 #

javascript
app.use(express.static('public', {
    maxAge: '1y',
    etag: true
}));

9.3 数据库连接池 #

javascript
mongoose.connect(process.env.DATABASE_URL, {
    maxPoolSize: 10,
    minPoolSize: 2
});

十、总结 #

部署要点:

步骤 说明
环境准备 环境变量、安全检查
进程管理 PM2集群模式
容器化 Docker部署
反向代理 Nginx配置
HTTPS SSL证书
CI/CD 自动化部署
监控 日志、APM

恭喜你完成了Express.js的学习之旅!

最后更新:2026-03-28