docker-compose 入门:多容器应用编排、网络与服务依赖管理
从零掌握 docker-compose:compose.yml 文件结构与核心字段(services/networks/volumes)、服务间网络通信与 DNS 解析、depends_on 与 healthcheck 组合实现有序启动、常用命令(up/down/logs/exec/scale)详解,以及 WordPress + MySQL、Flask + Redis + Nginx 完整多容器应用编排实战。
单个容器能运行一个服务,但真实应用通常由多个服务组成:Web 服务 + 数据库 + 缓存 + 消息队列……用 docker run 手动启动每个容器不仅繁琐,还难以管理依赖关系。docker-compose 用一个 YAML 文件描述整个应用的多容器结构,一条命令启动全部服务。
docker-compose 基础概念
compose.yml(或 docker-compose.yml)描述:
- 服务(Services):每个容器是一个服务
- 网络(Networks):服务间如何通信
- 数据卷(Volumes):数据如何持久化
文件名约定(按优先级):
compose.yaml ← 最新推荐(Docker Compose V2)
compose.yml
docker-compose.yaml
docker-compose.yml ← 旧版本常见
docker-compose vs Docker Compose:
docker-compose(V1):独立工具,需单独安装(python 写的)
docker compose(V2):Docker CLI 插件,随 Docker Engine 安装
推荐用 V2:docker compose up
一、compose.yml 基本结构
# compose.yml 顶层结构
version: "3.9" # 已废弃,新版本不需要写(自动检测)
services: # 服务定义(必须)
web: # 服务名称(自定义)
image: nginx # 使用现有镜像
# 或:build 指令构建镜像
db:
image: mysql:8.0
networks: # 网络定义(可选,不写会自动创建默认网络)
frontend:
backend:
volumes: # 数据卷定义(可选)
mysql_data:
二、services 字段详解
services:
web:
# 方式1:使用现有镜像
image: nginx:1.25-alpine
# 方式2:从 Dockerfile 构建
build:
context: ./app # Dockerfile 所在目录
dockerfile: Dockerfile.prod
args:
APP_VERSION: "1.2.0"
# 容器名称(不设置则自动生成 project_service_1)
container_name: web-prod
# 端口映射
ports:
- "80:80"
- "443:443"
- "127.0.0.1:8080:80" # 绑定特定 IP
# 环境变量
environment:
- NGINX_HOST=example.com
- NGINX_PORT=80
# 或从文件读取
env_file:
- .env
- .env.production
# 数据卷
volumes:
- ./html:/usr/share/nginx/html:ro # bind mount
- nginx_logs:/var/log/nginx # named volume
- type: bind # 详细格式
source: ./nginx.conf
target: /etc/nginx/nginx.conf
read_only: true
# 网络
networks:
- frontend
# 重启策略
restart: unless-stopped
# 资源限制
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
memory: 128M
# 健康检查
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
# 日志配置
logging:
driver: json-file
options:
max-size: "50m"
max-file: "3"
# 依赖关系
depends_on:
db:
condition: service_healthy # 等 db 健康后再启动
三、服务间网络通信
# 自定义网络(推荐:不同功能用不同网络)
services:
nginx:
networks:
- frontend
- backend
api:
networks:
- backend
db:
networks:
- backend
networks:
frontend: # nginx ↔ 用户
backend: # nginx ↔ api ↔ db(db 不暴露给 frontend)
# 服务间通信用服务名作为主机名
# api 服务内访问 db:
curl http://db:3306
# nginx 服务内访问 api:
curl http://api:8080
# DNS 解析规则:
# 服务名 → 该服务的容器 IP
# 多副本时(scale)→ 轮询负载均衡
四、depends_on 与启动顺序
# 问题:docker-compose up 默认并行启动所有服务
# 如果 api 在 db 准备好之前启动,会报"连接被拒绝"
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-psecret"]
interval: 5s
timeout: 3s
retries: 10
start_period: 30s
redis:
image: redis:7.2
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
retries: 5
api:
build: .
depends_on:
db:
condition: service_healthy # 等待 db 健康
redis:
condition: service_healthy # 等待 redis 健康
# ⚠️ depends_on 只控制启动顺序,不保证服务"完全就绪"
# 应用代码中仍需实现连接重试逻辑
nginx:
image: nginx:alpine
depends_on:
api:
condition: service_started # 等 api 容器启动(不检查健康状态)
ports:
- "80:80"
五、常用 compose 命令
# 启动所有服务(后台)
docker compose up -d
# 启动并强制重新构建镜像
docker compose up -d --build
# 只启动特定服务
docker compose up -d db redis
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f # 所有服务
docker compose logs -f api # 指定服务
docker compose logs --tail=100 api
# 进入容器
docker compose exec api bash
docker compose exec -u root db bash
# 在容器中执行命令(不进入交互模式)
docker compose exec db mysqladmin -u root -psecret status
# 停止服务(不删除容器和数据)
docker compose stop
# 停止并删除容器(保留 volumes)
docker compose down
# 停止并删除一切(包括 volumes)— 慎用!
docker compose down -v
# 重启特定服务
docker compose restart api
# 查看服务资源使用
docker compose top
# 拉取最新镜像(不重启)
docker compose pull
六、实战1:WordPress + MySQL
# compose.yml
services:
db:
image: mysql:8.0
container_name: wordpress-db
restart: unless-stopped
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppass123
MYSQL_ROOT_PASSWORD: rootsecret
volumes:
- mysql_data:/var/lib/mysql
networks:
- wordpress-net
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-u", "wpuser", "-pwppass123"]
interval: 10s
retries: 5
start_period: 30s
wordpress:
image: wordpress:6.4-php8.2-apache
container_name: wordpress-app
restart: unless-stopped
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db # 用服务名!
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppass123
volumes:
- wp_content:/var/www/html/wp-content
networks:
- wordpress-net
depends_on:
db:
condition: service_healthy
volumes:
mysql_data:
wp_content:
networks:
wordpress-net:
docker compose up -d
docker compose ps
# 访问 http://localhost:8080 完成 WordPress 安装
七、实战2:Flask + Redis + Nginx 三层架构
# compose.yml
services:
redis:
image: redis:7.2-alpine
restart: unless-stopped
networks:
- backend
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
retries: 3
api:
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
environment:
- REDIS_URL=redis://redis:6379 # 使用服务名
- APP_ENV=production
env_file:
- .env
networks:
- backend
depends_on:
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 15s
timeout: 5s
retries: 3
start_period: 10s
logging:
driver: json-file
options:
max-size: "50m"
max-file: "3"
nginx:
image: nginx:1.25-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
networks:
- frontend
- backend
depends_on:
api:
condition: service_healthy
networks:
frontend:
backend:
# nginx/nginx.conf
events { worker_connections 1024; }
http {
upstream api_backend {
server api:5000; # 使用服务名
}
server {
listen 80;
location / {
proxy_pass http://api_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
八、compose.yml 中的变量替换
# .env 文件(自动被 docker compose 加载)
APP_VERSION=1.2.0
DB_PASSWORD=secret123
NGINX_PORT=80
# compose.yml 中使用变量
services:
api:
image: myapp:${APP_VERSION} # 从 .env 读取
environment:
DB_PASSWORD: ${DB_PASSWORD}
nginx:
ports:
- "${NGINX_PORT:-80}:80" # 默认值语法:${VAR:-default}
# 覆盖 .env 变量
APP_VERSION=1.3.0 docker compose up -d
# 指定不同的 env 文件
docker compose --env-file .env.staging up -d
# 查看变量替换结果
docker compose config # 输出完整解析后的 compose.yml
小结
docker-compose 的核心价值:用代码(YAML)描述多容器应用的拓扑结构,一条命令替代多个 docker run,服务间自动通过名称互通。
关键要点:depends_on + healthcheck 组合实现有序启动(单独 depends_on 不可靠);自定义网络比默认网络提供更好的隔离和 DNS 解析;.env 文件管理环境差异,docker compose config 验证最终配置。
下一篇讲 docker-compose 进阶:profiles 多环境、override 文件、扩缩容与健康检查联动。
