掌握容器化部署:Docker 与 Docker Compose 实战 Node.js 微服务

引言:为什么选择 Docker 和 Docker Compose?

在分布式系统和微服务架构日益普及的今天,如何高效、可靠地部署和管理多个服务成为开发者面临的核心挑战。Docker 作为一种轻量级的容器化技术,通过将应用及其依赖打包成独立的容器,实现了环境一致性、资源隔离和快速部署。而 Docker Compose 则进一步简化了多容器应用的编排,通过一个 YAML 文件即可定义和管理多个关联的容器。

对于 Node.js 微服务而言,Docker 和 Docker Compose 的组合具有显著优势:

  • 环境一致性:避免“在我机器上能运行”的问题,确保开发、测试和生产环境完全一致。
  • 快速部署:容器启动速度快,适合频繁部署和弹性扩展的场景。
  • 资源隔离:每个微服务运行在独立的容器中,避免资源竞争和依赖冲突。
  • 简化编排:通过 Docker Compose 可以轻松定义服务间的依赖关系和网络配置。

本文将通过一个完整的示例,详细介绍如何使用 Docker 和 Docker Compose 部署 Node.js 微服务,涵盖从基础环境配置到多服务编排的全流程。

一、环境准备:安装 Docker 和 Docker Compose

在开始部署之前,需要确保本地环境已安装 Docker 和 Docker Compose。

1. 安装 Docker

Docker 支持在多种操作系统上运行,包括 Linux、macOS 和 Windows。以下是不同系统的安装方法:

Linux(以 Ubuntu 为例)

  1. # 卸载旧版本(如有)
  2. sudo apt-get remove docker docker-engine docker.io containerd runc
  3. # 安装依赖
  4. sudo apt-get update
  5. sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
  6. # 添加 Docker 官方 GPG 密钥
  7. curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  8. # 添加 Docker 仓库
  9. sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
  10. # 安装 Docker
  11. sudo apt-get update
  12. sudo apt-get install docker-ce docker-ce-cli containerd.io
  13. # 验证安装
  14. sudo docker run hello-world

macOS

通过 Docker 官方提供的安装包(Docker Desktop for Mac)进行安装,下载地址:https://www.docker.com/products/docker-desktop。

Windows

同样通过 Docker 官方安装包(Docker Desktop for Windows)进行安装,需确保系统支持 Hyper-V 或 WSL 2 后端。

2. 安装 Docker Compose

Docker Compose 通常随 Docker Desktop 一起安装。如果需要手动安装,可以按照以下步骤:

Linux/macOS

  1. # 下载最新版本的 Docker Compose
  2. sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  3. # 添加可执行权限
  4. sudo chmod +x /usr/local/bin/docker-compose
  5. # 验证安装
  6. docker-compose --version

Windows

通过 Docker Desktop 安装时,Docker Compose 会自动包含在内。

二、单个 Node.js 服务的容器化部署

1. 创建简单的 Node.js 服务

首先,创建一个简单的 Node.js Express 应用作为示例:

  1. mkdir nodejs-docker-demo
  2. cd nodejs-docker-demo
  3. npm init -y
  4. npm install express

创建 app.js 文件:

  1. const express = require('express');
  2. const app = express();
  3. const port = 3000;
  4. app.get('/', (req, res) => {
  5. res.send('Hello, Docker!');
  6. });
  7. app.listen(port, () => {
  8. console.log(`Server running at http://localhost:${port}`);
  9. });

2. 编写 Dockerfile

Dockerfile 是用于构建 Docker 镜像的脚本文件。在项目根目录下创建 Dockerfile

  1. # 使用官方 Node.js 镜像作为基础
  2. FROM node:14
  3. # 创建工作目录
  4. WORKDIR /usr/src/app
  5. # 复制 package.json 和 package-lock.json
  6. COPY package*.json ./
  7. # 安装依赖
  8. RUN npm install
  9. # 复制应用代码
  10. COPY . .
  11. # 暴露端口
  12. EXPOSE 3000
  13. # 定义启动命令
  14. CMD ["node", "app.js"]

3. 构建 Docker 镜像

运行以下命令构建镜像:

  1. docker build -t nodejs-docker-demo .

4. 运行容器

构建完成后,运行容器:

  1. docker run -p 3000:3000 nodejs-docker-demo

访问 http://localhost:3000,应该能看到“Hello, Docker!”的响应。

三、使用 Docker Compose 编排多服务

在实际的微服务架构中,通常需要部署多个相互依赖的服务。Docker Compose 通过一个 YAML 文件定义和管理这些服务。

1. 创建 Docker Compose 文件

在项目根目录下创建 docker-compose.yml

  1. version: '3.8'
  2. services:
  3. api:
  4. build: .
  5. ports:
  6. - "3000:3000"
  7. volumes:
  8. - .:/usr/src/app
  9. - /usr/src/app/node_modules
  10. environment:
  11. - NODE_ENV=development

2. 解释 Docker Compose 文件

  • version:指定 Compose 文件的版本。
  • services:定义服务列表,这里只有一个 api 服务。
  • build:指定构建上下文,. 表示当前目录。
  • ports:映射主机端口到容器端口。
  • volumes:挂载卷,实现代码热重载。
    • .:/usr/src/app:将当前目录挂载到容器的工作目录。
    • /usr/src/app/node_modules:匿名卷,避免覆盖容器内的 node_modules
  • environment:设置环境变量。

3. 启动服务

运行以下命令启动服务:

  1. docker-compose up

如果希望在后台运行,可以添加 -d 参数:

  1. docker-compose up -d

4. 验证服务

访问 http://localhost:3000,应该能看到相同的响应。修改 app.js 后,容器会自动重启(得益于卷挂载)。

四、进阶配置与最佳实践

1. 多阶段构建

为了减小镜像体积,可以使用多阶段构建。修改 Dockerfile

  1. # 第一阶段:构建
  2. FROM node:14 AS builder
  3. WORKDIR /usr/src/app
  4. COPY package*.json ./
  5. RUN npm install
  6. COPY . .
  7. RUN npm run build # 如果有构建步骤
  8. # 第二阶段:运行
  9. FROM node:14-slim
  10. WORKDIR /usr/src/app
  11. COPY --from=builder /usr/src/app/node_modules ./node_modules
  12. COPY --from=builder /usr/src/app .
  13. EXPOSE 3000
  14. CMD ["node", "app.js"]

2. 环境变量管理

对于生产环境,建议使用 .env 文件管理环境变量。创建 .env 文件:

  1. NODE_ENV=production
  2. PORT=3000

修改 docker-compose.yml

  1. version: '3.8'
  2. services:
  3. api:
  4. build: .
  5. ports:
  6. - "${PORT}:${PORT}"
  7. environment:
  8. - NODE_ENV=${NODE_ENV}

3. 健康检查

为服务添加健康检查,确保容器正常运行:

  1. version: '3.8'
  2. services:
  3. api:
  4. build: .
  5. ports:
  6. - "3000:3000"
  7. healthcheck:
  8. test: ["CMD", "curl", "-f", "http://localhost:3000"]
  9. interval: 30s
  10. timeout: 10s
  11. retries: 3

4. 网络配置

默认情况下,Docker Compose 会创建一个默认网络。如果需要自定义网络,可以显式定义:

  1. version: '3.8'
  2. services:
  3. api:
  4. build: .
  5. ports:
  6. - "3000:3000"
  7. networks:
  8. - my-network
  9. networks:
  10. my-network:
  11. driver: bridge

五、总结与展望

通过本文的介绍,读者已经掌握了如何使用 Docker 和 Docker Compose 部署 Node.js 微服务。从环境准备、单个服务的容器化部署,到多服务的编排与管理,Docker 和 Docker Compose 提供了强大的工具链,帮助开发者提升部署效率和可靠性。

未来,随着容器化技术的进一步发展,Docker 和 Docker Compose 将在微服务架构中发挥更加重要的作用。建议读者深入学习以下内容:

  • Docker Swarm 和 Kubernetes 的集群管理。
  • 持续集成/持续部署(CI/CD)与 Docker 的结合。
  • 安全最佳实践,如镜像扫描和最小权限原则。

通过不断实践和探索,读者可以构建出更加高效、可靠的微服务架构。