Docker Compose
Docker Compose 是用于定义和运行多容器 Docker 应用的工具。通过一个 YAML 配置文件,可以配置应用的服务、网络和数据卷。
什么是 Docker Compose?
Docker Compose 让你能够:
- 使用 YAML 文件定义多个服务
- 一键启动和停止整个应用栈
- 管理服务之间的依赖关系
- 轻松地在不同环境间复制配置
典型应用场景
- 开发环境:快速搭建完整的开发栈
- 自动化测试:定义测试所需的服务
- CI/CD 流水线:标准化构建和部署流程
- 单主机部署:中小型应用的部署
安装
Docker Desktop 已内置 Docker Compose,无需额外安装。
Linux 单独安装
# 下载最新版本
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker-compose --version
compose.yaml 文件结构
基本结构
# compose.yaml 或 docker-compose.yml
version: "3.8" # 可选,现代版本可省略
services:
# 定义服务
web:
image: nginx:latest
ports:
- "8080:80"
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: example
networks:
# 定义网络
app-network:
driver: bridge
volumes:
# 定义数据卷
db-data:
版本说明
version字段在现代 Docker Compose 中是可选的- 不同版本支持的功能略有不同
- 推荐使用最新版本或省略 version 字段
服务配置
基本配置
services:
web:
# 使用镜像
image: nginx:latest
# 或者使用构建
build: .
# 或者指定 Dockerfile 路径
build:
context: ./app
dockerfile: Dockerfile.dev
# 容器名称
container_name: my-web
# 主机名
hostname: web-server
# 重启策略
restart: always
端口映射
services:
web:
# 单个端口
ports:
- "8080:80"
# 多个端口
ports:
- "8080:80"
- "8443:443"
# 指定协议
ports:
- "53:53/udp"
# 仅暴露给其他服务(不映射到主机)
expose:
- "3000"
环境变量
services:
db:
# 直接设置
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: myapp
# 从文件读取
env_file:
- .env
- .env.local
# 列表格式
environment:
- MYSQL_ROOT_PASSWORD=root123
- MYSQL_DATABASE=myapp
.env 文件示例:
MYSQL_ROOT_PASSWORD=root123
MYSQL_DATABASE=myapp
MYSQL_USER=user
MYSQL_PASSWORD=password
数据卷
services:
db:
# 命名卷
volumes:
- db-data:/var/lib/mysql
# 绑定挂载
volumes:
- ./data:/var/lib/mysql
# 匿名卷
volumes:
- /var/lib/mysql
# 只读挂载
volumes:
- ./config:/etc/mysql/conf.d:ro
网络配置
services:
web:
# 指定网络
networks:
- frontend
- backend
# 设置网络别名
networks:
frontend:
aliases:
- app.local
networks:
frontend:
backend:
依赖关系
services:
web:
depends_on:
- db
- redis
# 等待条件(需要 healthcheck)
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
健康检查
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
资源限制
services:
web:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
网络配置
默认网络
Docker Compose 默认会创建一个网络,所有服务都连接到这个网络:
services:
web:
image: nginx
db:
image: mysql
# 自动创建 default 网络,服务之间可以通过服务名互相访问
自定义网络
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 内部网络,无法访问外网
使用已存在的网络
networks:
existing-network:
external: true
数据卷配置
命名卷
services:
db:
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:
driver: local
绑定挂载
services:
web:
volumes:
- ./app:/app
- ./config/nginx.conf:/etc/nginx/nginx.conf:ro
使用已存在的卷
volumes:
existing-volume:
external: true
实战示例
Web 应用栈
# compose.yaml
services:
# Web 前端
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./static:/usr/share/nginx/html:ro
depends_on:
- api
networks:
- frontend
# API 服务
api:
build: ./api
ports:
- "3000:3000"
environment:
NODE_ENV: production
DATABASE_URL: postgres://user:pass@db:5432/myapp
REDIS_URL: redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- frontend
- backend
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
# 数据库
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: myapp
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
interval: 10s
timeout: 5s
retries: 5
# 缓存
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
networks:
- backend
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
frontend:
backend:
volumes:
postgres-data:
redis-data:
开发环境
# compose.dev.yaml
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
environment:
NODE_ENV: development
volumes:
- .:/app
- /app/node_modules
command: npm run dev
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
POSTGRES_DB: devdb
ports:
- "5432:5432"
volumes:
- dev-db-data:/var/lib/postgresql/data
adminer:
image: adminer
ports:
- "8080:8080"
volumes:
dev-db-data:
WordPress
services:
wordpress:
image: wordpress:latest
ports:
- "80:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress-data:/var/www/html
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
volumes:
- db-data:/var/lib/mysql
volumes:
wordpress-data:
db-data:
常用命令
启动和停止
# 启动所有服务
docker compose up
# 后台启动
docker compose up -d
# 构建并启动
docker compose up --build
# 启动特定服务
docker compose up nginx db
# 停止所有服务
docker compose down
# 停止并删除数据卷
docker compose down -v
# 停止但不删除容器
docker compose stop
# 启动已停止的服务
docker compose start
# 重启服务
docker compose restart
查看状态
# 查看运行中的服务
docker compose ps
# 查看日志
docker compose logs
# 实时查看日志
docker compose logs -f
# 查看特定服务日志
docker compose logs nginx
# 查看资源使用
docker compose top
执行命令
# 在服务中执行命令
docker compose exec nginx bash
# 以 root 用户执行
docker compose exec -u root nginx bash
# 运行一次性命令
docker compose run --rm npm install
其他命令
# 拉取镜像
docker compose pull
# 构建镜像
docker compose build
# 推送镜像
docker compose push
# 验证配置文件
docker compose config
# 查看服务镜像
docker compose images
# 暂停和恢复
docker compose pause
docker compose unpause
高级特性
Profiles(服务配置组)
Profiles 允许你将服务分组,按需启动不同的服务组合:
services:
# 始终启动的核心服务
app:
image: myapp
ports:
- "3000:3000"
# 开发环境专用服务
db:
image: postgres
profiles:
- dev
ports:
- "5432:5432"
adminer:
image: adminer
profiles:
- dev
- debug
ports:
- "8080:8080"
# 调试工具
debug-tool:
image: nicolaka/netshoot
profiles:
- debug
command: sleep infinity
使用 profiles:
# 只启动核心服务(无 profiles)
docker compose up -d
# 启动 dev 配置组
docker compose --profile dev up -d
# 启动多个配置组
docker compose --profile dev --profile debug up -d
# 启动特定服务(即使有 profiles)
docker compose up app adminer
# 查看所有服务(包括未启用的 profiles)
docker compose config --services
典型应用场景:
services:
app:
image: myapp
# 测试专用数据库
test-db:
image: postgres
profiles:
- test
# 性能测试工具
k6:
image: loadimpact/k6
profiles:
- load-test
volumes:
- ./scripts:/scripts
# 监控栈
prometheus:
image: prom/prometheus
profiles:
- monitoring
grafana:
image: grafana/grafana
profiles:
- monitoring
depends_on 高级配置
除了简单的服务依赖,还支持条件检查:
services:
web:
image: nginx
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
# service_healthy 依赖此配置
redis:
image: redis
# service_started 是默认条件,无需 healthcheck
依赖条件类型:
| 条件 | 说明 |
|---|---|
service_started | 服务已启动(默认) |
service_healthy | 服务健康检查通过 |
service_completed_successfully | 服务成功完成并退出 |
等待初始化容器完成:
services:
# 初始化容器
init-db:
image: postgres:15
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
command: >
sh -c "postgres && pg_isready && psql -c 'CREATE DATABASE myapp'"
depends_on:
db:
condition: service_healthy
# 主应用等待初始化完成
app:
image: myapp
depends_on:
init-db:
condition: service_completed_successfully
扩展字段(YAML Anchor)
使用 YAML 锚点复用配置:
# 定义共享配置
x-common-env: &common-env
TZ: Asia/Shanghai
LOG_LEVEL: info
x-common-healthcheck: &common-healthcheck
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
services:
app:
image: myapp
environment:
<<: *common-env
APP_NAME: app1
healthcheck:
<<: *common-healthcheck
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
api:
image: myapi
environment:
<<: *common-env
APP_NAME: api1
healthcheck:
<<: *common-healthcheck
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
include 引入其他配置文件
Docker Compose 支持引入其他配置文件:
# compose.yaml
include:
- ./docker/compose.database.yaml
- ./docker/compose.cache.yaml
- ./docker/compose.monitoring.yaml
services:
app:
image: myapp
depends_on:
- db
- redis
database.yaml:
services:
db:
image: postgres:15
volumes:
- db-data:/var/lib/docker
volumes:
db-data:
extends 继承服务配置
# common-service.yaml
services:
base:
image: node:18-alpine
working_dir: /app
environment:
NODE_ENV: production
restart: unless-stopped
# compose.yaml
services:
api:
extends:
file: common-service.yaml
service: base
command: node api.js
ports:
- "3000:3000"
worker:
extends:
file: common-service.yaml
service: base
command: node worker.js
资源配置和约束
services:
app:
image: myapp
deploy:
# 资源限制
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
# 副本数(Swarm 模式)
replicas: 3
# 更新策略
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
# 重启策略
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
# 放置约束
placement:
constraints:
- node.role == manager
- node.labels.region == cn-east
服务扩缩容
# 扩展服务实例
docker compose up -d --scale app=3
# 缩减服务
docker compose up -d --scale app=1
# 使用端口范围
services:
app:
ports:
- "3000-3005:3000" # 支持多实例
构建配置详解
services:
app:
build:
# 构建上下文
context: ./app
# Dockerfile 路径
dockerfile: Dockerfile.prod
# 构建参数
args:
- NODE_VERSION=18
- BUILD_ENV=production
# 构建缓存来源
cache_from:
- myapp:latest
# 标签
labels:
- "com.example.description=My App"
# 目标阶段(多阶段构建)
target: production
# 额外构建上下文
additional_contexts:
- tools=./tools
# SSH 配置
ssh:
- default
多环境配置
使用多个配置文件
# 基础配置 + 开发环境覆盖
docker compose -f compose.yaml -f compose.dev.yaml up
# 基础配置 + 生产环境覆盖
docker compose -f compose.yaml -f compose.prod.yaml up -d
compose.dev.yaml:
services:
app:
build:
dockerfile: Dockerfile.dev
volumes:
- .:/app
environment:
NODE_ENV: development
compose.prod.yaml:
services:
app:
build:
dockerfile: Dockerfile
environment:
NODE_ENV: production
deploy:
replicas: 3
使用环境变量
services:
app:
image: myapp:${APP_VERSION:-latest}
environment:
DATABASE_URL: ${DATABASE_URL}
.env 文件:
APP_VERSION=1.0.0
DATABASE_URL=postgres://localhost:5432/myapp
最佳实践
1. 使用明确的镜像版本
# 不好
image: nginx
# 好
image: nginx:1.24-alpine
2. 合理命名服务
# 使用有意义的服务名
services:
frontend:
# ...
backend-api:
# ...
database-primary:
# ...
cache-redis:
# ...
3. 配置健康检查
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
4. 使用网络隔离
services:
web:
networks:
- public
api:
networks:
- public
- private
db:
networks:
- private
networks:
public:
private:
internal: true
5. 合理使用卷
# 开发环境:绑定挂载(实时更新)
volumes:
- ./app:/app
# 生产环境:命名卷(持久化)
volumes:
- app-data:/app/data
小结
本章我们学习了:
- Docker Compose 的作用和应用场景
- compose.yaml 文件结构
- 服务配置:镜像、端口、环境变量、卷、网络
- 网络和数据卷配置
- 多环境配置方案
- 常用命令
- 最佳实践
练习
- 创建一个包含 Nginx 和 PHP 的 Web 服务栈
- 配置服务之间的依赖关系和健康检查
- 使用多配置文件管理开发/生产环境
- 实现一个完整的 Web 应用栈(前端 + API + 数据库 + 缓存)
- 练习常用命令:启动、停止、查看日志、进入容器