Docker Compose 完整教程
Docker Compose 是一个用于定义和管理多容器 Docker 应用程序的工具。通过一个 YAML 文件来配置应用程序的服务,然后使用一个命令就可以创建并启动所有服务。
1. Docker Compose 基础概念
1.1 核心概念
- Service(服务):应用程序的一个组件,如数据库、Web服务器等
- Project(项目):由一组关联的服务组成的完整应用程序
- Container(容器):服务的运行实例
1.2 主要优势
- 简化多容器应用的部署和管理
- 通过代码定义基础设施(Infrastructure as Code)
- 便于开发、测试和生产环境的一致性
- 支持服务扩缩容和负载均衡
2. 安装 Docker Compose
2.1 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
2.2 通过 pip 安装
pip install docker-compose
3. Compose 文件结构
**Docker Compose 使用 YAML 文件来定义服务。文件通常命名为 **docker-compose.yml
。
3.1 基本结构
version: '3.8' # Compose文件格式版本
services: # 定义服务
service1:
# 服务1配置
service2:
# 服务2配置
volumes: # 定义数据卷(可选)
volume1:
networks: # 定义网络(可选)
network1:
configs: # 定义配置(可选)
config1:
secrets: # 定义密钥(可选)
secret1:
4. 服务配置详解
4.1 镜像相关
image - 指定镜像
services:
web:
image: nginx:1.21-alpine
app:
image: my-app:latest
db:
image: postgres:13
build - 构建镜像
services:
web:
build: . # 使用当前目录的Dockerfile
app:
build:
context: ./app # 构建上下文路径
dockerfile: Dockerfile.dev # 指定Dockerfile
args: # 构建参数
- BUILD_ENV=development
- VERSION=1.0
target: development # 多阶段构建目标
4.2 端口映射
ports - 暴露端口
services:
web:
image: nginx
ports:
- "8080:80" # 主机端口:容器端口
- "443:443"
- "127.0.0.1:8081:80" # 绑定到特定IP
expose - 内部端口暴露
services:
app:
image: my-app
expose:
- "3000" # 只在内部网络中暴露,不映射到主机
4.3 环境变量
environment - 设置环境变量
services:
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
# 或使用数组形式
# - POSTGRES_DB=myapp
# - POSTGRES_USER=user
env_file - 从文件加载环境变量
services:
app:
image: my-app
env_file:
- .env
- .env.local
4.4 数据卷
volumes - 挂载数据卷
services:
web:
image: nginx
volumes:
- ./html:/usr/share/nginx/html:ro # 主机路径:容器路径:权限
- nginx-config:/etc/nginx/conf.d # 命名卷
- /var/log/nginx # 匿名卷
volumes:
nginx-config: # 定义命名卷
4.5 网络配置
networks - 网络设置
services:
web:
image: nginx
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 内部网络,不能访问外网
4.6 依赖关系
depends_on - 服务依赖
services:
web:
image: nginx
depends_on:
- app
- db
app:
image: my-app
depends_on:
db:
condition: service_healthy # 等待健康检查通过
db:
image: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 30s
timeout: 10s
retries: 3
4.7 重启策略
restart - 重启策略
services:
web:
image: nginx
restart: always # 总是重启
app:
image: my-app
restart: unless-stopped # 除非手动停止
worker:
image: my-worker
restart: on-failure # 失败时重启
temp:
image: temp-service
restart: "no" # 不重启(默认)
4.8 资源限制
deploy - 部署配置
services:
web:
image: nginx
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
replicas: 3
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
4.9 健康检查
healthcheck - 健康检查
services:
web:
image: nginx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
4.10 其他常用字段
services:
app:
image: my-app
container_name: my-app-container # 自定义容器名
hostname: app-server # 容器主机名
user: 1000:1000 # 运行用户
working_dir: /app # 工作目录
command: ["python", "app.py"] # 覆盖默认命令
entrypoint: ["/entrypoint.sh"] # 覆盖入口点
stdin_open: true # 等同于 docker run -i
tty: true # 等同于 docker run -t
privileged: true # 特权模式
cap_add: # 添加Linux能力
- SYS_ADMIN
cap_drop: # 移除Linux能力
- NET_ADMIN
devices: # 设备映射
- "/dev/sda:/dev/sda"
dns: # DNS服务器
- 8.8.8.8
- 8.8.4.4
extra_hosts: # 额外的主机映射
- "api.example.com:192.168.1.100"
logging: # 日志配置
driver: json-file
options:
max-size: "200k"
max-file: "10"
5. 实战示例
5.1 简单 Web 应用示例
项目结构:
webapp/
├── docker-compose.yml
├── .env
├── nginx/
│ └── nginx.conf
├── app/
│ ├── Dockerfile
│ ├── app.py
│ └── requirements.txt
└── data/
docker-compose.yml:
version: '3.8'
services:
# Nginx 反向代理
nginx:
image: nginx:1.21-alpine
container_name: webapp-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
depends_on:
- app
networks:
- frontend
restart: unless-stopped
# Python Web 应用
app:
build:
context: ./app
dockerfile: Dockerfile
container_name: webapp-app
environment:
- FLASK_ENV=production
- DATABASE_URL=postgresql://user:password@db:5432/webapp
volumes:
- ./app:/app
- app-logs:/app/logs
depends_on:
db:
condition: service_healthy
networks:
- frontend
- backend
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 30s
timeout: 10s
retries: 3
# PostgreSQL 数据库
db:
image: postgres:13-alpine
container_name: webapp-db
environment:
POSTGRES_DB: webapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres-data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- backend
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d webapp"]
interval: 30s
timeout: 5s
retries: 5
# Redis 缓存
redis:
image: redis:6-alpine
container_name: webapp-redis
command: redis-server --appendonly yes
volumes:
- redis-data:/data
networks:
- backend
restart: unless-stopped
# 后台任务处理器
worker:
build:
context: ./app
dockerfile: Dockerfile
container_name: webapp-worker
command: celery -A app.celery worker --loglevel=info
environment:
- CELERY_BROKER_URL=redis://redis:6379/0
- DATABASE_URL=postgresql://user:password@db:5432/webapp
volumes:
- ./app:/app
- worker-logs:/app/logs
depends_on:
- redis
- db
networks:
- backend
restart: unless-stopped
volumes:
postgres-data:
redis-data:
app-logs:
worker-logs:
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true
.env 文件:
# 数据库配置
POSTGRES_DB=webapp
POSTGRES_USER=user
POSTGRES_PASSWORD=your_secure_password
# 应用配置
FLASK_ENV=production
SECRET_KEY=your_secret_key
# Redis配置
REDIS_URL=redis://redis:6379/0
5.2 微服务架构示例
version: '3.8'
services:
# API Gateway
gateway:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./gateway/nginx.conf:/etc/nginx/nginx.conf
depends_on:
- user-service
- product-service
- order-service
networks:
- public
# 用户服务
user-service:
build: ./services/user-service
environment:
- DATABASE_URL=postgresql://user:pass@user-db:5432/users
- JWT_SECRET=user_jwt_secret
depends_on:
- user-db
networks:
- public
- user-network
deploy:
replicas: 2
user-db:
image: postgres:13
environment:
POSTGRES_DB: users
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- user-db-data:/var/lib/postgresql/data
networks:
- user-network
# 商品服务
product-service:
build: ./services/product-service
environment:
- MONGO_URL=mongodb://product-db:27017/products
depends_on:
- product-db
networks:
- public
- product-network
deploy:
replicas: 2
product-db:
image: mongo:4.4
volumes:
- product-db-data:/data/db
networks:
- product-network
# 订单服务
order-service:
build: ./services/order-service
environment:
- DATABASE_URL=postgresql://user:pass@order-db:5432/orders
- USER_SERVICE_URL=http://user-service:3000
- PRODUCT_SERVICE_URL=http://product-service:3000
depends_on:
- order-db
networks:
- public
- order-network
order-db:
image: postgres:13
environment:
POSTGRES_DB: orders
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- order-db-data:/var/lib/postgresql/data
networks:
- order-network
# 消息队列
rabbitmq:
image: rabbitmq:3-management
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: admin
ports:
- "15672:15672" # 管理界面
volumes:
- rabbitmq-data:/var/lib/rabbitmq
networks:
- message-queue
# 监控服务
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
networks:
- monitoring
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
depends_on:
- prometheus
networks:
- monitoring
volumes:
user-db-data:
product-db-data:
order-db-data:
rabbitmq-data:
prometheus-data:
grafana-data:
networks:
public:
driver: bridge
user-network:
driver: bridge
internal: true
product-network:
driver: bridge
internal: true
order-network:
driver: bridge
internal: true
message-queue:
driver: bridge
monitoring:
driver: bridge
5.3 开发环境示例
version: '3.8'
services:
# 开发用Web服务器
web:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app # 代码热重载
- /app/node_modules # 避免覆盖node_modules
environment:
- NODE_ENV=development
- CHOKIDAR_USEPOLLING=true # 支持文件监听
depends_on:
- db
- redis
networks:
- dev-network
# 数据库(开发用)
db:
image: postgres:13
environment:
POSTGRES_DB: app_dev
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
ports:
- "5432:5432" # 暴露端口便于调试
volumes:
- dev-db-data:/var/lib/postgresql/data
- ./db/seeds:/docker-entrypoint-initdb.d # 测试数据
networks:
- dev-network
# Redis(开发用)
redis:
image: redis:alpine
ports:
- "6379:6379"
networks:
- dev-network
# 邮件测试服务
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025" # SMTP
- "8025:8025" # Web UI
networks:
- dev-network
# 文件同步服务(可选)
sync:
image: alpine
command: >
sh -c "apk add --no-cache inotify-tools &&
while inotifywait -r -e modify,create,delete,move /app; do
echo 'Files changed'
done"
volumes:
- .:/app
networks:
- dev-network
volumes:
dev-db-data:
networks:
dev-network:
driver: bridge
6. 高级功能
6.1 多环境配置
基础配置 docker-compose.yml:
version: '3.8'
services:
web:
image: my-app:latest
ports:
- "80:80"
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
开发环境覆盖 docker-compose.override.yml:
services:
web:
build: .
volumes:
- .:/app
environment:
- DEBUG=true
db:
ports:
- "5432:5432"
生产环境覆盖 docker-compose.prod.yml:
services:
web:
deploy:
replicas: 3
resources:
limits:
memory: 512M
restart: always
db:
volumes:
- db-data:/var/lib/postgresql/data
restart: always
volumes:
db-data:
6.2 配置和密钥管理
version: '3.8'
services:
web:
image: nginx
configs:
- source: nginx-config
target: /etc/nginx/nginx.conf
secrets:
- ssl-cert
- ssl-key
configs:
nginx-config:
file: ./nginx.conf
secrets:
ssl-cert:
file: ./ssl/cert.pem
ssl-key:
file: ./ssl/key.pem
6.3 扩展和include
docker-compose.yml:
version: '3.8'
include:
- docker-compose.base.yml
- docker-compose.monitoring.yml
services:
app:
extends:
file: docker-compose.base.yml
service: base-app
environment:
- NODE_ENV=production
7. 常用命令
7.1 基础命令
# 启动服务
docker-compose up # 启动所有服务
docker-compose up -d # 后台启动
docker-compose up web db # 启动指定服务
# 停止服务
docker-compose down # 停止并删除容器
docker-compose down -v # 同时删除数据卷
docker-compose stop # 仅停止容器
# 查看状态
docker-compose ps # 查看服务状态
docker-compose logs # 查看日志
docker-compose logs -f web # 实时查看指定服务日志
# 执行命令
docker-compose exec web bash # 进入容器
docker-compose run web python manage.py migrate # 运行一次性命令
7.2 管理命令
# 构建镜像
docker-compose build # 构建所有服务
docker-compose build --no-cache web # 强制重新构建
# 拉取镜像
docker-compose pull # 拉取所有镜像
# 扩缩容
docker-compose up -d --scale web=3 # 扩展web服务到3个实例
# 重启服务
docker-compose restart # 重启所有服务
docker-compose restart web # 重启指定服务
# 配置验证
docker-compose config # 验证并显示配置
docker-compose config --services # 列出所有服务名
7.3 多环境命令
# 使用不同的compose文件
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 使用环境变量文件
docker-compose --env-file .env.prod up -d
# 指定项目名
docker-compose -p myproject up -d
8. 最佳实践
8.1 文件组织
project/
├── docker-compose.yml # 主配置文件
├── docker-compose.override.yml # 开发环境覆盖
├── docker-compose.prod.yml # 生产环境配置
├── .env # 环境变量
├── .env.example # 环境变量示例
├── dockerfiles/ # Dockerfile目录
│ ├── app/
│ └── nginx/
├── config/ # 配置文件目录
│ ├── nginx/
│ └── postgres/
└── data/ # 持久化数据目录
8.2 安全建议
- **使用 **
.env
文件管理敏感信息,不要提交到版本控制 - 为数据库等服务使用强密码
- 限制容器的资源使用
- 使用非root用户运行容器
- 定期更新基础镜像
8.3 性能优化
- 使用多阶段构建减小镜像大小
- 合理设置健康检查间隔
- 使用适当的重启策略
- 配置资源限制防止资源耗尽
8.4 开发效率
- **使用 **
docker-compose.override.yml
进行本地开发配置 - 挂载代码目录实现热重载
- **使用 **
depends_on
和健康检查确保服务启动顺序 - 合理使用网络隔离
9. 故障排除
9.1 常见问题
# 服务无法启动
docker-compose logs service-name # 查看服务日志
docker-compose config # 验证配置文件
# 网络连接问题
docker network ls # 查看网络
docker-compose exec service ping target # 测试连通性
# 数据卷问题
docker volume ls # 查看数据卷
docker-compose down -v # 删除数据卷重新开始
# 端口占用
netstat -tulpn | grep :8080 # 检查端口占用
docker-compose ps # 查看端口映射
9.2 调试技巧
- **使用 **
docker-compose config
验证配置 - **通过 **
docker-compose logs -f
实时查看日志 - **使用 **
docker-compose exec
进入容器调试 - 检查环境变量是否正确传递
10. 总结
Docker Compose 是管理多容器应用的强大工具。通过本教程,你应该能够:
- 理解 Docker Compose 的基本概念和文件结构
- 掌握各种服务配置选项的使用方法
- 编写适用于不同场景的 compose 文件
- 使用最佳实践来组织和管理项目
- 解决常见的部署和运行问题