Node.js 后端工程化:从模块化到 Docker 容器化部署全流程

1. 模块化开发
  • CommonJS 规范:Node.js 原生支持的模块系统
    // math.js
    module.exports = {
      add: (a, b) => a + b,
      multiply: (a, b) => a * b
    };
    
    // app.js
    const math = require('./math.js');
    console.log(math.add(2, 3)); // 输出: 5
    

  • ES Modules (ESM):现代 JavaScript 标准
    // utils.mjs
    export const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
    
    // main.mjs
    import { capitalize } from './utils.mjs';
    console.log(capitalize('hello')); // 输出: Hello
    

2. 依赖管理与工程化
  • 包管理:使用 npmyarn
    # 初始化项目
    npm init -y
    
    # 安装依赖
    npm install express dotenv mongoose
    

  • 环境配置:通过 .env 管理敏感信息
    DB_HOST=cluster.mongodb.net
    DB_USER=admin
    PORT=3000
    

3. 代码质量保障
  • ESLint + Prettier:代码规范与格式化
    // .eslintrc.json
    {
      "extends": ["airbnb-base", "prettier"],
      "plugins": ["prettier"],
      "rules": {
        "prettier/prettier": "error"
      }
    }
    

  • 测试框架:Jest + Supertest
    // __tests__/api.test.js
    const request = require('supertest');
    const app = require('../app');
    
    test('GET /api/users', async () => {
      const res = await request(app).get('/api/users');
      expect(res.statusCode).toEqual(200);
      expect(res.body).toHaveProperty('data');
    });
    

4. 容器化部署
  • Dockerfile 配置
    # 基础镜像
    FROM node:18-alpine
    
    # 工作目录
    WORKDIR /app
    
    # 依赖安装
    COPY package*.json ./
    RUN npm ci --only=production
    
    # 应用代码
    COPY . .
    
    # 暴露端口
    EXPOSE 3000
    
    # 启动命令
    CMD ["node", "server.js"]
    

  • 构建与运行容器
    # 构建镜像
    docker build -t my-node-app .
    
    # 运行容器
    docker run -d -p 3000:3000 --env-file .env --name node-container my-node-app
    

5. 持续集成/部署 (CI/CD)
  • GitHub Actions 示例 (.github/workflows/deploy.yml)
    name: Node.js CI/CD
    
    on:
      push:
        branches: [ main ]
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - name: Build Docker image
            run: docker build -t my-registry/my-node-app:${{ github.sha }} .
          - name: Push to Docker Hub
            run: |
              docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PASS }}
              docker push my-registry/my-node-app:${{ github.sha }}
      deploy:
        needs: build
        runs-on: ubuntu-latest
        steps:
          - name: Deploy to server
            run: |
              ssh user@server "docker pull my-registry/my-node-app:${{ github.sha }}"
              ssh user@server "docker stop live-app || true"
              ssh user@server "docker run -d -p 3000:3000 --name live-app my-registry/my-node-app:${{ github.sha }}"
    

6. 监控与日志
  • 日志管理:使用 winstonmorgan
    const winston = require('winston');
    const logger = winston.createLogger({
      level: 'info',
      format: winston.format.json(),
      transports: [new winston.transports.File({ filename: 'combined.log' })]
    });
    

  • 健康检查端点
    app.get('/health', (req, res) => {
      res.status(200).json({ 
        status: 'UP', 
        db: checkDbConnection() ? 'connected' : 'down' 
      });
    });
    

关键工程化原则
  1. 关注点分离:路由、服务、数据访问层解耦
  2. 配置即代码:环境变量 > 配置文件 > 硬编码
  3. 不可变基础设施:容器镜像构建后不再修改
  4. 12-Factor 应用:云原生应用设计准则

完整流程:本地开发 → 版本控制 → CI测试 → 容器构建 → 镜像仓库 → 生产部署 → 监控告警。通过容器化实现环境一致性,解决"在我机器上能跑"的问题。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐