在前面的课程中,我们学习了如何使用 Docker 容器来运行单个服务。
通过 docker run 命令,我们可以快速启动一个数据库、一个 Web 服务器或者一个缓存服务。这种方式在开发简单应用时非常有效。
然而,随着应用架构的演进,微服务的理念逐渐流行,一个应用由多个服务共同组成。
本节课我们准备了 一个多服务的web应用 的案例如下:
四个服务共同组成了应用,整体架构图如下:
试想一下,我们为了部署这个web应用,需要完成哪些工作?
可以看到,随着工程复杂度的提升,服务数量增加,手动管理服务容器会变得越来越复杂。 这不仅增加了运维的复杂度,还增加了手动操作出错的概率。
所以我们需要一个工具来对多容器应用进行管理。 于是Docker Compose应运而生。
Docker Compose 是一个用于定义和运行多容器的工具。 它允许我们使用 YAML 文件来定义各容器,然后通过一个命令来启动所有服务。
docker compose up: 创建和启动所有服务Docker Compose 使用 YAML 文件来定义服务。 YAML 是一种人类可读的数据序列化语言,它支持多种数据类型,如字符串、数字、列表、映射等。 Docker Compose 使用 YAML 文件来定义服务,因此我们需要了解 YAML 的基本语法。
流程:
nginx 服务
frontend 服务
backend 服务
mongodb 服务
mongodb_data 持久化数据库数据docker compose build: 构建镜像docker compose up: 创建和启动所有服务docker compose down: 停止和删除所有服务docker compose ps: 查看服务状态docker compose logs: 查看服务日志在后台启动服务
docker compose up -d
查看服务状态
docker compose ps
查看服务日志
docker compose logs frontend docker compose logs backend docker compose logs mongodb
停止所有服务
docker compose down
重新构建服务
docker compose build [${service}]
当 service 省略时,默认构建所有配置了 build 的服务。
重启单个服务
docker compose restart frontend
在实际项目中,我们经常需要管理不同环境(开发、测试、生产)的配置。 Docker Compose 提供了灵活的环境变量管理机制,让我们能够轻松地在不同环境之间切换配置。
services:
backend:
image: node:18
environment:
- NODE_ENV=development
- PORT=3001
- DATABASE_HOST=mongodb
优点:简单直观,配置集中
缺点:敏感信息(如密码)会暴露在版本控制中
在 compose.yaml 同级目录创建 .env 文件:
# .env 文件
NODE_ENV=development
MONGODB_PORT=27017
MONGODB_DATABASE=todos
MONGODB_ROOT_USER=admin
MONGODB_ROOT_PASSWORD=secret123
在 compose.yaml 中引用:
services:
mongodb:
image: mongo:6
environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGODB_ROOT_USER}
- MONGO_INITDB_ROOT_PASSWORD=${MONGODB_ROOT_PASSWORD}
ports:
- "${MONGODB_PORT}:27017"
优点:敏感信息与配置分离,可以将 .env 加入 .gitignore
缺点:需要额外维护 .env 文件
services:
backend:
image: node:18
env_file:
- ./backend.env # 后端专用配置
- ./common.env # 公共配置
优点:可以按服务或功能拆分配置文件
缺点:文件较多时管理复杂
创建 .env.example 模板文件
# .env.example - 提交到 Git,作为配置模板
NODE_ENV=development
MONGODB_PORT=27017
MONGODB_DATABASE=todos
MONGODB_ROOT_USER=
MONGODB_ROOT_PASSWORD=
将 .env 加入 .gitignore
# .gitignore
.env
.env.local
.env.*.local
为不同环境创建专用配置
.env # 默认开发环境 .env.production # 生产环境 .env.test # 测试环境
使用有意义的变量命名
# ❌ 不推荐
DB_P=3306
# ✅ 推荐
MYSQL_PORT=3306
# 在 5_compose 目录下创建 .env.example
cat > .env.example << 'EOF'
# ===================
# 应用环境配置
# ===================
NODE_ENV=development
# ===================
# 服务端口配置
# ===================
NGINX_PORT=8080
FRONTEND_PORT=3000
BACKEND_PORT=3001
# ===================
# MongoDB 配置
# ===================
MONGODB_PORT=27017
MONGODB_DATABASE=todos
MONGODB_ROOT_USER=admin
MONGODB_ROOT_PASSWORD=
# ===================
# API 配置
# ===================
API_URL=/api
EOF
# 复制模板并填写实际值
cp .env.example .env
# 编辑 .env 文件,填写密码等敏感信息
# MONGODB_ROOT_PASSWORD=your_secure_password_here
创建 compose.env.yaml 展示最佳实践:
services:
# Nginx 反向代理
nginx:
build: ./nginx
ports:
- "${NGINX_PORT:-8080}:80" # 提供默认值
depends_on:
- frontend
- backend
# 前端服务
frontend:
build: ./frontend
expose:
- "${FRONTEND_PORT:-3000}"
environment:
- NODE_ENV=${NODE_ENV:-development}
- REACT_APP_API_URL=${API_URL:-/api}
depends_on:
- backend
volumes:
- ./frontend:/app
- /app/node_modules
# 后端服务
backend:
build: ./backend
expose:
- "${BACKEND_PORT:-3001}"
environment:
- NODE_ENV=${NODE_ENV:-development}
- MONGODB_URI=mongodb://${MONGODB_ROOT_USER}:${MONGODB_ROOT_PASSWORD}@mongodb:${MONGODB_PORT:-27017}/${MONGODB_DATABASE:-todos}?authSource=admin
depends_on:
- mongodb
volumes:
- ./backend:/app
- /app/node_modules
# MongoDB 数据库
mongodb:
image: mongo:6
expose:
- "${MONGODB_PORT:-27017}"
environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGODB_ROOT_USER:-admin}
- MONGO_INITDB_ROOT_PASSWORD=${MONGODB_ROOT_PASSWORD:?请在.env文件中设置MONGODB_ROOT_PASSWORD}
- MONGO_INITDB_DATABASE=${MONGODB_DATABASE:-todos}
volumes:
- mongodb_data:/data/db
volumes:
mongodb_data:
| 语法 | 说明 | 示例 |
|---|---|---|
${VAR} | 直接引用变量 | ${MONGODB_PORT} |
${VAR:-default} | 变量未设置时使用默认值 | ${MONGODB_PORT:-27017} |
${VAR:?error} | 变量未设置时报错并退出 | ${PASSWORD:?密码不能为空} |
${VAR:+value} | 变量已设置时使用替代值 | ${DEBUG:+--verbose} |
# 查看 compose 解析后的完整配置(包含变量替换结果)
docker compose config
# 仅查看某个服务的配置
docker compose config --services
# 验证配置文件语法
docker compose config --quiet && echo "配置文件语法正确"
# 开发环境(默认读取 .env)
docker compose up -d
# 生产环境
docker compose --env-file .env.production up -d
# 测试环境
docker compose --env-file .env.test up -d
services:
# 仅在开发环境启用的调试工具
mongo-express:
image: mongo-express
profiles:
- debug
environment:
- ME_CONFIG_MONGODB_SERVER=mongodb
ports:
- "8081:8081"
# 启动时包含调试工具
docker compose --profile debug up -d
# 生产环境不包含调试工具
docker compose up -d
| 场景 | 推荐方案 |
|---|---|
| 简单项目/本地开发 | 直接在 compose.yaml 中定义 |
| 团队协作项目 | .env + .env.example 模板 |
| 微服务架构 | env_file 按服务拆分配置 |
| 多环境部署 | .env.{environment} + --env-file |
| 敏感信息管理 | Docker Secrets(生产环境推荐) |
通过合理使用环境变量和 .env 文件,我们可以: