Skip to content

Docker Compose 部署 Node.js 项目

Docker Compose 是部署 Node.js 项目的理想工具,它可以通过一个简单的 YAML 文件定义和运行多容器应用。下面我将详细介绍如何使用 Docker Compose 部署 Node.js 项目,包括基础配置、开发与生产环境优化以及常见问题解决方案。

1. 项目准备与基础配置

1.1 项目结构准备

一个典型的 Node.js 项目结构如下:

my-node-app/
├── src/
│   └── app.js         # 应用入口文件
├── package.json       # 项目依赖
├── Dockerfile         # 构建镜像配置
└── docker-compose.yml # 服务编排配置

1.2 创建基础 Node.js 应用

src/app.js中添加一个简单的 Express 应用示例:

javascript
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3000;

app.get("/", (req, res) => {
  res.send("Node.js in Docker with Compose!");
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

package.json中配置脚本和依赖:

json
{
  "name": "nodejs-docker",
  "version": "1.0.0",
  "main": "src/app.js",
  "scripts": {
    "start": "node src/app.js",
    "dev": "nodemon src/app.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  },
  "devDependencies": {
    "nodemon": "^3.1.0"
  }
}

2. Docker 相关配置

2.1 创建 Dockerfile

在项目根目录创建Dockerfile,建议使用多阶段构建优化镜像大小:

dockerfile
# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build  # 如果有构建步骤

# 生产阶段
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/dist ./dist  # 如果有构建产物
COPY --from=builder /app/src ./src    # 复制源代码

EXPOSE 3000
CMD ["npm", "start"]

2.2 创建 docker-compose.yml

在项目根目录创建docker-compose.yml文件:

yaml
version: "3.8"
services:
  node-app:
    build: .
    container_name: my-node-app
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - TZ=Asia/Shanghai
    volumes:
      - ./src:/app/src # 开发时代码同步
      - /app/node_modules # 避免覆盖容器内的依赖
    restart: unless-stopped
    command: npm run dev # 开发时使用nodemon

3. 启动与验证

3.1 启动容器

运行以下命令构建并启动容器:

bash
docker-compose up --build -d

3.2 验证运行

查看日志确认应用是否正常启动:

bash
docker-compose logs -f

访问http://localhost:3000应该能看到"Node.js in Docker with Compose!"的响应。

4. 环境配置优化

4.1 开发环境配置

对于开发环境,可以启用热更新和调试支持:

yaml
services:
  node-app:
    # ...其他配置
    volumes:
      - ./:/app # 挂载整个项目目录
      - /app/node_modules
    command: npm run dev
    environment:
      - NODE_ENV=development
      - DEBUG=express:*
    ports:
      - "3000:3000"
      - "9229:9229" # Node.js调试端口

4.2 生产环境配置

创建docker-compose.prod.yml用于生产环境:

yaml
version: "3.8"
services:
  node-app:
    build:
      context: .
      dockerfile: Dockerfile.prod # 专门的生产Dockerfile
    ports:
      - "80:3000"
    environment:
      - NODE_ENV=production
    restart: always
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 512M

对应的Dockerfile.prod:

dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

5. 高级配置选项

5.1 添加数据库服务

docker-compose.yml中添加 PostgreSQL 服务:

yaml
services:
  # ...node-app配置

  postgres:
    image: postgres:15
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mypassword
      POSTGRES_DB: mydb
    volumes:
      - postgres-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    networks:
      - app-network

volumes:
  postgres-data:

networks:
  app-network:
    driver: bridge

5.2 使用 PM2 管理 Node 进程

修改Dockerfile.prod的 CMD 指令:

dockerfile
RUN npm install -g pm2
CMD ["pm2-runtime", "start", "processes.json"]

5.3 多服务组合部署

完整示例包含前端、后端和数据库:

yaml
version: "3.8"
services:
  frontend:
    build: ./frontend
    ports:
      - "80:80"
    depends_on:
      - backend

  backend:
    build: ./backend
    ports:
      - "3000:3000"
    environment:
      - DB_HOST=postgres
    depends_on:
      - postgres

  postgres:
    image: postgres
    environment:
      POSTGRES_PASSWORD: example
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  postgres-data:

6. 常见问题与解决方案

6.1 依赖安装问题

  • 问题:容器内依赖安装失败
  • 解决方案:确保package.jsonpackage-lock.json已复制到容器,并在安装前执行:
dockerfile
COPY package*.json ./
RUN npm install

6.2 端口冲突

  • 问题:端口已被占用
  • 解决方案:修改docker-compose.yml中的端口映射:
yaml
ports:
  - "4000:3000" # 宿主机4000映射到容器3000

6.3 文件权限问题

  • 问题:容器内文件权限错误
  • 解决方案:在 Dockerfile 中使用非 root 用户:
dockerfile
RUN adduser -D appuser && chown -R appuser /app
USER appuser

7. 生产环境最佳实践

  1. 使用轻量级基础镜像:如node:18-alpine而非完整版 Node 镜像

  2. 多阶段构建:分离构建环境和运行环境,减少最终镜像大小

  3. 环境变量管理:使用.env文件管理敏感信息:

yaml
services:
  node-app:
    env_file:
      - .env
  1. 日志管理:配置日志轮转和外部日志收集

  2. 健康检查:添加容器健康检查:

yaml
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
  interval: 30s
  timeout: 10s
  retries: 3

8. 常用命令参考

命令描述
docker-compose up -d启动服务(后台模式)
docker-compose down停止并移除容器
docker-compose logs -f查看实时日志
docker-compose ps查看服务状态
docker-compose exec node-app sh进入容器 shell
docker-compose restart node-app重启指定服务

通过以上配置和最佳实践,你可以高效地使用 Docker Compose 部署 Node.js 项目,无论是开发环境还是生产环境。根据项目需求,可以灵活扩展数据库、缓存等其他服务。