Docker Compose完全指南
2025/9/17大约 8 分钟
Docker Compose完全指南
前置知识
在开始本教程之前,建议您具备以下基础知识:
- Docker基础概念
- YAML文件格式
- 基本的网络知识
Docker Compose简介
1. 什么是Docker Compose?
Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。使用Compose,您可以:
- 在单个文件中定义应用程序的服务
- 使用单个命令创建和启动所有服务
- 管理服务之间的依赖关系
- 简化开发和测试环境的搭建
2. 工作原理
graph TB
A[docker-compose.yml] --> B[解析配置文件]
B --> C[创建网络]
C --> D[创建数据卷]
D --> E[启动服务容器]
E --> F[依赖服务编排]
基础配置详解
1. 版本配置
# 声明docker-compose.yml文件的版本
# version: 指定Docker Compose文件格式的版本号
# 不同版本支持的功能和语法可能不同
version: '3.8'
版本说明:
- 1.x版本:基础功能,已不推荐使用
- 2.x版本:增加了更多编排功能
- 3.x版本:当前主流版本,支持Docker Swarm
- 3.8:支持GPU资源、自定义构建上下文等
- 3.9:支持seccomp策略、部署时更新配置等
2. 服务定义
version: '3.8'
services: # services: 定义所有需要运行的服务
web: # web: 服务名称,可自定义
# image: 指定要使用的Docker镜像,格式为[仓库/]镜像名[:标签]
image: nginx:alpine
# build: 指定如何构建镜像的配置
build:
# context: 构建上下文路径,包含Dockerfile和其他需要的文件
context: ./web
# dockerfile: 指定要使用的Dockerfile文件名
dockerfile: Dockerfile.dev
# args: 构建时传递给Dockerfile的参数
args:
VERSION: '1.0'
# container_name: 指定容器名称,如果不指定则自动生成
container_name: my-web
# restart: 容器重启策略
# no: 不自动重启
# always: 总是重启
# on-failure: 失败时重启
# unless-stopped: 除非手动停止,否则重启
restart: unless-stopped
# ports: 端口映射配置,格式为"主机端口:容器端口"
ports:
- "80:80" # 将容器的80端口映射到主机的80端口
- "443:443" # 将容器的443端口映射到主机的443端口
# environment: 设置容器的环境变量
environment:
NODE_ENV: production # 直接设置键值对
API_URL: http://api:3000 # 可以引用其他服务名称
# volumes: 数据卷挂载配置
volumes:
- ./html:/usr/share/nginx/html:ro # ro表示只读挂载
- ./logs:/var/log/nginx # 日志目录挂载
# deploy: 部署相关的配置,主要用于Swarm模式
deploy:
# replicas: 指定运行的副本数量
replicas: 2
# resources: 资源限制配置
resources:
limits: # 资源使用上限
cpus: '0.50' # 最多使用50%的CPU
memory: 512M # 最多使用512MB内存
reservations: # 资源预留配置
cpus: '0.25' # 预留25%的CPU
memory: 256M # 预留256MB内存
# update_config: 更新策略配置
update_config:
parallelism: 2 # 同时更新的容器数
delay: 10s # 更新间隔时间
# restart_policy: 重启策略配置
restart_policy:
condition: on-failure # 失败时重启
# 数据库服务配置
db:
image: mysql:8.0
# environment: 环境变量配置
environment:
MYSQL_ROOT_PASSWORD: example # 设置root密码
MYSQL_DATABASE: myapp # 创建初始数据库
# volumes: 数据持久化配置
volumes:
- db_data:/var/lib/mysql # 使用命名卷存储数据
# healthcheck: 健康检查配置
healthcheck:
# test: 健康检查命令
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
# interval: 检查间隔时间
interval: 10s
# timeout: 检查超时时间
timeout: 5s
# retries: 重试次数
retries: 5
# start_period: 启动等待时间
start_period: 30s
3. 网络配置
version: '3.8'
services:
web:
# networks: 定义服务使用的网络
networks:
frontend: # 前端网络配置
ipv4_address: 172.16.238.10 # 指定固定IP地址
backend: # 后端网络配置
aliases: # 网络别名配置
- webapp
api:
networks:
backend:
ipv4_address: 172.16.238.11
# networks: 定义项目的网络
networks:
# frontend: 前端网络名称
frontend:
# driver: 网络驱动类型
# bridge: 单机桥接网络
# host: 使用主机网络
# overlay: Swarm集群网络
# macvlan: 允许设置MAC地址的网络
driver: bridge
# driver_opts: 驱动选项配置
driver_opts:
com.docker.network.bridge.name: frontend
# ipam: IP地址管理配置
ipam:
driver: default # 使用默认IPAM驱动
config:
- subnet: 172.16.238.0/24 # 子网配置
gateway: 172.16.238.1 # 网关地址
# labels: 为网络添加元数据标签
labels:
com.example.description: "前端网络"
# backend: 后端网络名称
backend:
driver: bridge
# internal: true表示该网络无法访问外网
internal: true
# enable_ipv6: 是否启用IPv6
enable_ipv6: true
ipam:
config:
- subnet: 172.16.239.0/24
4. 数据卷配置
version: '3.8'
services:
db:
# volumes: 数据卷配置
volumes:
# 命名卷配置
- type: volume
source: db_data # 卷名称
target: /var/lib/mysql # 容器内挂载点
volume:
nocopy: true # 不复制容器内已存在的数据
# 绑定挂载配置
- type: bind
source: ./config # 主机目录
target: /etc/mysql/conf.d # 容器内路径
read_only: true # 只读挂载
# tmpfs配置(临时文件系统)
- type: tmpfs
target: /tmp # 挂载到容器的临时目录
tmpfs:
size: 1000000 # 大小限制(字节)
# volumes: 定义命名卷
volumes:
# db_data: 卷名称
db_data:
# driver: 存储驱动类型
driver: local
# driver_opts: 驱动选项
driver_opts:
type: nfs # NFS类型
o: addr=10.0.0.1,rw # NFS选项
device: ":/path/to/dir" # NFS路径
# labels: 卷标签
labels:
com.example.description: "数据库存储"
高级特性
1. 依赖管理
version: '3.8'
services:
web:
# depends_on: 定义服务依赖关系
depends_on:
# db: 依赖的服务名称
db:
# condition: 依赖条件
# service_started: 服务已启动
# service_healthy: 服务健康检查通过
# service_completed_successfully: 服务成功完成
condition: service_healthy
# restart: 依赖服务重启时是否重启本服务
restart: true
redis:
condition: service_started
db:
# healthcheck: 健康检查配置
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s # 检查间隔
timeout: 5s # 超时时间
retries: 5 # 重试次数
start_period: 30s # 启动等待时间
2. 环境变量管理
version: '3.8'
services:
web:
# env_file: 从文件加载环境变量
env_file:
- ./web.env # web服务的环境变量文件
- ./common.env # 公共环境变量文件
# environment: 直接设置环境变量
environment:
- NODE_ENV=production # 直接设置值
- API_KEY=${API_KEY} # 使用环境变量
- DEBUG=false # 布尔值
# secrets: 密钥配置
secrets:
- source: api_key # 密钥源
target: api_key.txt # 容器内路径
uid: '103' # 用户ID
gid: '103' # 组ID
mode: 0440 # 访问权限
# secrets: 定义密钥
secrets:
# api_key: 密钥名称
api_key:
file: ./api_key.txt # 从文件加载
# db_password: 外部密钥
db_password:
external: true # 使用外部已存在的密钥
实战配置示例
1. Web应用开发环境
version: '3.8'
services:
# frontend: 前端服务
frontend:
# build: 构建配置
build:
context: ./frontend # 构建上下文
target: development # 构建目标阶段
args: # 构建参数
NODE_ENV: development
# volumes: 开发环境挂载
volumes:
- ./frontend:/app # 源码挂载
- /app/node_modules # 依赖目录
ports:
- "3000:3000" # 开发服务器端口
environment:
- NODE_ENV=development
- REACT_APP_API_URL=http://localhost:8080
command: ["npm", "start"] # 启动命令
# backend: 后端服务
backend:
build: ./backend
volumes:
- ./backend:/app # 源码挂载
ports:
- "8080:8080" # API端口
environment:
- SPRING_PROFILES_ACTIVE=dev
- DB_HOST=db
- REDIS_HOST=cache
# depends_on: 依赖配置
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
# db: 数据库服务
db:
image: postgres:13-alpine
volumes:
- postgres_data:/var/lib/postgresql/data # 数据持久化
- ./init.sql:/docker-entrypoint-initdb.d/init.sql # 初始化脚本
environment:
- POSTGRES_USER=myapp
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=myapp_dev
# healthcheck: 健康检查
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myapp"]
interval: 5s
timeout: 5s
retries: 5
# cache: 缓存服务
cache:
image: redis:alpine
ports:
- "6379:6379" # Redis端口
volumes:
- redis_data:/data # 数据持久化
# volumes: 数据卷定义
volumes:
postgres_data:
driver: local
redis_data:
driver: local
2. 微服务架构
version: '3.8'
services:
# gateway: API网关服务
gateway:
image: nginx:alpine
ports:
- "80:80" # HTTP端口
- "443:443" # HTTPS端口
# configs: 配置文件
configs:
- source: nginx_conf
target: /etc/nginx/nginx.conf
# secrets: SSL证书
secrets:
- source: ssl_cert
target: /etc/nginx/ssl/cert.pem
- source: ssl_key
target: /etc/nginx/ssl/key.pem
# deploy: 部署配置
deploy:
replicas: 2 # 运行2个副本
update_config:
order: start-first # 先启动新版本
# auth_service: 认证服务
auth_service:
build: ./auth
environment:
- REDIS_HOST=cache
- JWT_SECRET_FILE=/run/secrets/jwt_secret
secrets:
- jwt_secret # JWT密钥
deploy:
replicas: 2
resources:
limits:
memory: 256M # 内存限制
# user_service: 用户服务
user_service:
build: ./user
depends_on:
- db
- cache
environment:
- DB_HOST=db
- CACHE_HOST=cache
deploy:
replicas: 2
# cache: Redis缓存
cache:
image: redis:alpine
volumes:
- cache_data:/data
configs:
- source: redis_conf
target: /usr/local/etc/redis/redis.conf
# db: MySQL数据库
db:
image: mysql:8.0
volumes:
- db_data:/var/lib/mysql
configs:
- source: mysql_conf
target: /etc/mysql/conf.d/custom.cnf
secrets:
- db_root_password
environment:
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_root_password
# volumes: 持久化存储
volumes:
cache_data:
driver: local
db_data:
driver: local
# configs: 配置文件
configs:
nginx_conf:
file: ./config/nginx.conf
mysql_conf:
file: ./config/mysql.cnf
redis_conf:
file: ./config/redis.conf
# secrets: 敏感数据
secrets:
ssl_cert:
file: ./secrets/cert.pem
ssl_key:
file: ./secrets/key.pem
jwt_secret:
file: ./secrets/jwt_secret
db_root_password:
file: ./secrets/db_password
最佳实践
1. 项目结构
./
├── docker-compose.yml # 主配置文件
├── docker-compose.override.yml # 开发环境覆盖配置
├── docker-compose.prod.yml # 生产环境配置
├── .env # 环境变量
├── services/ # 服务目录
│ ├── frontend/
│ │ ├── Dockerfile
│ │ ├── .dockerignore
│ │ └── src/
│ ├── backend/
│ │ ├── Dockerfile
│ │ ├── .dockerignore
│ │ └── src/
│ └── nginx/
│ ├── Dockerfile
│ └── nginx.conf
├── config/ # 配置文件
│ ├── mysql/
│ │ └── custom.cnf
│ └── redis/
│ └── redis.conf
├── secrets/ # 密钥文件
│ ├── cert.pem
│ ├── key.pem
│ └── jwt_secret
└── scripts/ # 辅助脚本
├── backup.sh
└── deploy.sh
注意事项
配置管理
- 使用环境变量文件
- 区分开发和生产配置
- 避免硬编码敏感信息
- 使用secrets管理密钥
资源管理
- 设置资源限制
- 使用数据卷备份
- 配置日志轮转
- 监控资源使用
网络安全
- 使用内部网络
- 限制端口暴露
- 配置安全组
- 启用TLS加密
常见问题
1. 服务启动顺序问题?
解决方案:
- 使用depends_on配置
depends_on: db: condition: service_healthy
- 实现健康检查
healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s timeout: 10s retries: 3
- 添加重试机制
deploy: restart_policy: condition: on-failure max_attempts: 3
- 使用wait-for-it脚本
command: ["./wait-for-it.sh", "db:5432", "--", "npm", "start"]
2. 数据持久化问题?
处理方法:
- 使用命名卷
volumes: db_data: driver: local driver_opts: type: none device: /data/mysql o: bind
- 配置备份策略
# 创建备份脚本 docker run --rm \ -v myapp_data:/source:ro \ -v /backup:/backup \ alpine tar czf /backup/data-$(date +%Y%m%d).tar.gz -C /source .
- 使用外部存储
volumes: db_data: driver: rexray/ebs driver_opts: size: 20
- 设置权限
volumes: - type: volume source: db_data target: /var/lib/mysql volume: nocopy: true
3. 网络连接问题?
排查步骤:
- 检查网络配置
networks: backend: driver: bridge internal: true
- 验证服务发现
docker-compose exec web ping api
- 测试端口映射
ports: - target: 80 published: 8080 protocol: tcp mode: host
- 查看容器日志
docker-compose logs -f web
总结
本教程详细介绍了Docker Compose的使用,包括:
- ✅ 基础配置:版本、服务、网络、数据卷
- ✅ 高级特性:依赖管理、环境变量、密钥管理
- ✅ 实战示例:开发环境、微服务架构
- ✅ 最佳实践:项目结构、配置管理、安全考虑
- ✅ 问题解决:启动顺序、数据持久化、网络连接
下一步学习
- 探索Docker Swarm集群管理
- 了解Kubernetes容器编排
- 学习CI/CD集成部署
- 实践容器监控方案