Docker 容器化 Node.js 应用实战:从开发到生产
·
Docker 容器化 Node.js 应用实战:从开发到生产
前言很多团队在项目初期不考虑容器化,等项目变大、部署环境变多时,"在我机器上能跑"就成了噩梦。本文以一个 Express.js REST API 为例,演示如何将 Node.js 应用容器化,并配合 Docker Compose 管理多容器架构。全文实战导向,代码可直接复用。—### 1. 准备项目结构假设项目结构如下:my-api/├── src/│ └── index.js├── tests/│ └── index.test.js├── Dockerfile├── docker-compose.yml├── .dockerignore└── package.json依赖文件 package.json:json{ "name": "my-api", "version": "1.0.0", "scripts": { "start": "node src/index.js", "test": "jest" }, "dependencies": { "express": "^4.18.2" }, "devDependencies": { "jest": "^29.7.0" }}````src/index.js` 写一个简单的 API:javascriptconst express = require(‘express’);const app = express();const PORT = process.env.PORT || 3000;app.get(‘/health’, (req, res) => { res.json({ status: ‘ok’, timestamp: new Date().toISOString() });});app.get(‘/api/hello’, (req, res) => { const name = req.query.name || ‘World’; res.json({ message: Hello, ${name}! });});app.listen(PORT, () => { console.log(Server running on port ${PORT});});module.exports = app;---### 2. 编写 Dockerfile(多阶段构建)采用**多阶段构建**,最终镜像只包含生产依赖,体积最小化:dockerfile# ---- 构建阶段 ----FROM node:20-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ci --only=productionCOPY . .# ---- 最终阶段 ----FROM node:20-alpine AS productionWORKDIR /app# 使用非 root 用户运行,增强安全性RUN addgroup -g 1001 -S nodejs && \ adduser -S nodeapp -u 1001COPY --from=builder --chown=nodeapp:nodejs /app/node_modules ./node_modulesCOPY --chown=nodeapp:nodejs ./src ./srcCOPY --chown=nodeapp:nodejs package*.json ./USER nodeappEXPOSE 3000ENV NODE_ENV=productionENV PORT=3000CMD [“node”, “src/index.js”]**要点说明:**- `node:20-alpine` 基础镜像远小于 Debian 版(约 170MB vs 1GB+)- `npm ci` 优于 `npm install`,锁版本、速度快- 创建非 root 用户并以 `USER nodeapp` 切换,是生产安全的标配---### 3. .dockerignore 与 docker-compose.yml**`.dockerignore`** 排除不需要打包进镜像的文件:node_modulesnpm-debug.log.git.gitignore*.mdtests.env.env.***`docker-compose.yml`** 管理应用 + MySQL + Redis 的完整开发环境:yamlversion: '3.8’services: api: build: context: . target: production ports: - “3000:3000” environment: - NODE_ENV=production - DB_HOST=db - REDIS_HOST=redis depends_on: db: condition: service_healthy redis: condition: service_started restart: unless-stopped healthcheck: test: [“CMD”, “wget”, “-qO-”, “http://localhost:3000/health”] interval: 30s timeout: 10s retries: 3 db: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: root_secret MYSQL_DATABASE: myapp volumes: - db_data:/var/lib/mysql healthcheck: test: [“CMD”, “mysqladmin”, “ping”, “-h”, “localhost”] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine volumes: - redis_data:/datavolumes: db_data: redis_data:---### 4. 构建与运行bash# 开发环境启动(前台)docker compose up# 生产构建 + 后台运行docker compose -f docker-compose.yml -f docker-compose.prod.yml builddocker compose -f docker-compose.yml -f docker-compose.prod.yml up -d# 查看日志docker compose logs -f api# 进入容器调试docker compose exec api sh```—### 5. 生产环境额外建议| 方面 | 建议 ||------|------|| 镜像扫描 | 用 trivy image my-api:latest 扫描漏洞 || 资源限制 | 在 docker-compose.prod.yml 中加 deploy.resources.limits || 健康检查 | 生产环境务必配置 healthcheck,配合 K8s/负载均衡做滚动更新 || 日志收集 | 输出到 stdout,由 Docker Daemon 收集,不要写文件 || 多阶段构建 | 如需构建前端,可再加一个 nginx 服务阶段 |—### 总结本文演示了 Node.js 应用的完整容器化流程:多阶段 Dockerfile 减小镜像体积、非 root 用户提升安全隔离、docker-compose 管理多容器依赖与健康检查。核心收益是环境一致性问题从根源上消失——开发、测试、生产跑的是同一份镜像。容器化不是终点,而是 DevOps 自动化的起点。有了容器基础,之后接入 CI/CD、监控告警、灰度发布都会顺畅很多。
更多推荐





所有评论(0)