Docker Compose
🎯 学习目标
- 深入理解Docker Compose的概念和工作原理
- 掌握docker-compose.yml文件的编写技巧
- 学会多容器应用的编排和管理
- 了解服务发现、负载均衡和扩缩容机制
📚 Docker Compose概述
1. 什么是Docker Compose
javascript
// Docker Compose概念
const dockerCompose = {
definition: '用于定义和运行多容器Docker应用的工具',
core_concepts: {
service: '应用的组成部分,如web服务、数据库等',
project: '一组相关联的服务',
container: '服务的运行实例'
},
workflow: [
'定义应用环境 (Dockerfile)',
'定义服务组合 (docker-compose.yml)',
'启动完整应用 (docker-compose up)'
],
advantages: [
'简化多容器应用部署',
'环境一致性保证',
'开发生产环境统一',
'服务依赖管理',
'一键启停扩缩容'
],
use_cases: [
'开发环境搭建',
'自动化测试',
'单机部署',
'原型验证'
]
};
console.log('Docker Compose概念:', dockerCompose);
2. 基本命令
bash
# 基础操作
docker-compose up # 启动所有服务
docker-compose up -d # 后台启动
docker-compose up --build # 重新构建并启动
docker-compose down # 停止并删除容器
docker-compose down -v # 同时删除数据卷
# 服务管理
docker-compose start # 启动已存在的容器
docker-compose stop # 停止服务
docker-compose restart # 重启服务
docker-compose pause # 暂停服务
docker-compose unpause # 恢复服务
# 查看状态
docker-compose ps # 查看服务状态
docker-compose logs # 查看日志
docker-compose logs -f web # 实时查看web服务日志
docker-compose top # 查看运行进程
# 执行命令
docker-compose exec web bash # 进入web服务容器
docker-compose run web ls # 在新容器中运行命令
# 扩缩容
docker-compose up --scale web=3 # 扩展web服务到3个实例
docker-compose scale web=2 # 缩减web服务到2个实例
📝 docker-compose.yml详解
1. 基本结构
yaml
# docker-compose.yml基本结构
version: '3.8' # Compose文件版本
services: # 服务定义
web:
# 服务配置
db:
# 服务配置
volumes: # 数据卷定义(可选)
# 卷配置
networks: # 网络定义(可选)
# 网络配置
secrets: # 密钥定义(可选)
# 密钥配置
configs: # 配置定义(可选)
# 配置项
2. 服务配置详解
yaml
version: '3.8'
services:
web:
# 镜像配置
image: nginx:alpine # 使用现有镜像
# build: . # 或从Dockerfile构建
# 构建配置
build:
context: . # 构建上下文
dockerfile: Dockerfile.prod # 指定Dockerfile
args: # 构建参数
NODE_ENV: production
API_URL: https://api.example.com
target: production # 多阶段构建目标
# 容器配置
container_name: my-web-server # 自定义容器名
hostname: web-server # 容器主机名
# 端口映射
ports:
- "80:80" # 主机端口:容器端口
- "443:443"
- "127.0.0.1:8080:8080" # 绑定特定IP
# 环境变量
environment:
- NODE_ENV=production # 数组格式
- DEBUG=false
# 或对象格式
environment:
NODE_ENV: production
DEBUG: false
# 环境变量文件
env_file:
- .env
- .env.production
# 数据卷
volumes:
- ./src:/app/src # 绑定挂载
- node_modules:/app/node_modules # 命名卷
- /tmp # 匿名卷
# 网络配置
networks:
- frontend
- backend
# 依赖关系
depends_on:
- db
- redis
# 健康检查
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# 重启策略
restart: unless-stopped # no, always, on-failure, unless-stopped
# 资源限制
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
# 日志配置
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
# 安全配置
user: "1000:1000" # 用户ID:组ID
read_only: true # 只读根文件系统
tmpfs:
- /tmp
- /var/cache
# 标签
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`example.com`)"
3. 完整应用示例
yaml
# docker-compose.yml - 完整的Web应用栈
version: '3.8'
services:
# 前端服务
frontend:
build:
context: ./frontend
target: production
container_name: myapp-frontend
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ssl-certs:/etc/ssl/certs:ro
networks:
- frontend
depends_on:
- backend
restart: unless-stopped
labels:
- "com.example.description=Frontend service"
- "com.example.department=engineering"
# 后端API服务
backend:
build:
context: ./backend
dockerfile: Dockerfile.prod
args:
NODE_ENV: production
container_name: myapp-backend
ports:
- "3000:3000"
environment:
NODE_ENV: production
DATABASE_URL: postgresql://app:${DB_PASSWORD}@database:5432/myapp
REDIS_URL: redis://cache:6379
JWT_SECRET: ${JWT_SECRET}
env_file:
- .env.production
volumes:
- app-uploads:/app/uploads
- app-logs:/app/logs
networks:
- frontend
- backend
depends_on:
database:
condition: service_healthy
cache:
condition: service_started
healthcheck:
test: ["CMD", "node", "healthcheck.js"]
interval: 30s
timeout: 5s
retries: 3
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
# 数据库服务
database:
image: postgres:13
container_name: myapp-database
environment:
POSTGRES_DB: myapp
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d myapp"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
deploy:
resources:
limits:
memory: 512M
# 缓存服务
cache:
image: redis:alpine
container_name: myapp-cache
command: redis-server --appendonly yes
volumes:
- redis-data:/data
networks:
- backend
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
restart: unless-stopped
# 消息队列
queue:
image: rabbitmq:3-management
container_name: myapp-queue
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD}
ports:
- "15672:15672" # 管理界面
volumes:
- rabbitmq-data:/var/lib/rabbitmq
networks:
- backend
restart: unless-stopped
# 工作进程
worker:
build:
context: ./backend
target: worker
container_name: myapp-worker
environment:
NODE_ENV: production
DATABASE_URL: postgresql://app:${DB_PASSWORD}@database:5432/myapp
REDIS_URL: redis://cache:6379
RABBITMQ_URL: amqp://admin:${RABBITMQ_PASSWORD}@queue:5672
volumes:
- app-logs:/app/logs
networks:
- backend
depends_on:
- database
- cache
- queue
restart: unless-stopped
deploy:
replicas: 2
# 数据卷定义
volumes:
postgres-data:
driver: local
redis-data:
driver: local
rabbitmq-data:
driver: local
app-uploads:
driver: local
app-logs:
driver: local
ssl-certs:
external: true # 外部创建的卷
# 网络定义
networks:
frontend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
backend:
driver: bridge
internal: true # 内部网络,无外网访问
🚀 高级功能
1. 多环境配置
yaml
# docker-compose.yml (基础配置)
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
NODE_ENV: development
volumes:
- .:/app
- /app/node_modules
db:
image: postgres:13
environment:
POSTGRES_DB: myapp_dev
POSTGRES_PASSWORD: dev123
yaml
# docker-compose.override.yml (开发环境覆盖)
version: '3.8'
services:
web:
volumes:
- .:/app:cached # macOS性能优化
environment:
DEBUG: true
HOT_RELOAD: true
command: npm run dev
db:
ports:
- "5432:5432" # 暴露数据库端口用于调试
yaml
# docker-compose.prod.yml (生产环境)
version: '3.8'
services:
web:
image: myapp:${TAG:-latest}
environment:
NODE_ENV: production
deploy:
replicas: 3
resources:
limits:
cpus: '0.5'
memory: 512M
restart: unless-stopped
db:
environment:
POSTGRES_DB: myapp_prod
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres-prod-data:/var/lib/postgresql/data
volumes:
postgres-prod-data:
external: true
2. 环境变量管理
bash
# .env文件
COMPOSE_PROJECT_NAME=myapp
COMPOSE_FILE=docker-compose.yml:docker-compose.override.yml
# 应用配置
NODE_ENV=development
API_PORT=3000
DB_PASSWORD=secret123
JWT_SECRET=your-jwt-secret-here
RABBITMQ_PASSWORD=rabbitmq123
# Docker配置
TAG=latest
REGISTRY=myregistry.com
bash
# .env.production
COMPOSE_PROJECT_NAME=myapp-prod
COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml
NODE_ENV=production
API_PORT=3000
DB_PASSWORD=super-secret-password
JWT_SECRET=production-jwt-secret
RABBITMQ_PASSWORD=production-rabbitmq-password
TAG=v1.2.3
REGISTRY=production-registry.com
3. 服务扩缩容
bash
# 启动时指定副本数
docker-compose up --scale web=3 --scale worker=2
# 动态扩缩容
docker-compose scale web=5
docker-compose scale worker=3
# 使用配置文件定义副本数
# docker-compose.yml
services:
web:
deploy:
replicas: 3
worker:
deploy:
replicas: 2
🛠️ 实际应用场景
1. 微服务架构
yaml
# docker-compose.microservices.yml
version: '3.8'
services:
# API网关
gateway:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./gateway/nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- frontend
depends_on:
- user-service
- order-service
- product-service
# 用户服务
user-service:
build: ./services/user-service
environment:
SERVICE_NAME: user-service
DATABASE_URL: postgresql://user:${USER_DB_PASSWORD}@user-db:5432/users
networks:
- frontend
- user-backend
depends_on:
- user-db
user-db:
image: postgres:13
environment:
POSTGRES_DB: users
POSTGRES_USER: user
POSTGRES_PASSWORD: ${USER_DB_PASSWORD}
volumes:
- user-db-data:/var/lib/postgresql/data
networks:
- user-backend
# 订单服务
order-service:
build: ./services/order-service
environment:
SERVICE_NAME: order-service
DATABASE_URL: postgresql://order:${ORDER_DB_PASSWORD}@order-db:5432/orders
USER_SERVICE_URL: http://user-service:3000
networks:
- frontend
- order-backend
depends_on:
- order-db
order-db:
image: postgres:13
environment:
POSTGRES_DB: orders
POSTGRES_USER: order
POSTGRES_PASSWORD: ${ORDER_DB_PASSWORD}
volumes:
- order-db-data:/var/lib/postgresql/data
networks:
- order-backend
# 产品服务
product-service:
build: ./services/product-service
environment:
SERVICE_NAME: product-service
DATABASE_URL: mongodb://product-db:27017/products
networks:
- frontend
- product-backend
depends_on:
- product-db
product-db:
image: mongo:5.0
volumes:
- product-db-data:/data/db
networks:
- product-backend
# 服务发现和配置
consul:
image: consul:latest
ports:
- "8500:8500"
networks:
- frontend
- user-backend
- order-backend
- product-backend
volumes:
user-db-data:
order-db-data:
product-db-data:
networks:
frontend:
user-backend:
internal: true
order-backend:
internal: true
product-backend:
internal: true
2. 开发环境工具栈
yaml
# docker-compose.dev.yml
version: '3.8'
services:
# 应用服务
app:
build:
context: .
target: development
volumes:
- .:/app
- /app/node_modules
ports:
- "3000:3000"
- "9229:9229" # Node.js调试端口
environment:
NODE_ENV: development
DEBUG: app:*
networks:
- dev-network
depends_on:
- postgres
- redis
- mailhog
# 数据库
postgres:
image: postgres:13
environment:
POSTGRES_DB: dev_db
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev123
ports:
- "5432:5432"
volumes:
- postgres-dev-data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
networks:
- dev-network
# 缓存
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
# 数据库管理工具
pgadmin:
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_PASSWORD: admin123
ports:
- "5050:80"
networks:
- dev-network
depends_on:
- postgres
# Redis管理工具
redis-commander:
image: rediscommander/redis-commander
environment:
REDIS_HOSTS: local:redis:6379
ports:
- "8081:8081"
networks:
- dev-network
depends_on:
- redis
# 文档服务
docs:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./docs:/usr/share/nginx/html:ro
networks:
- dev-network
volumes:
postgres-dev-data:
networks:
dev-network:
driver: bridge
3. CI/CD测试环境
yaml
# docker-compose.test.yml
version: '3.8'
services:
# 测试数据库
test-db:
image: postgres:13
environment:
POSTGRES_DB: test_db
POSTGRES_USER: test
POSTGRES_PASSWORD: test123
tmpfs:
- /var/lib/postgresql/data # 使用内存存储提高速度
# 单元测试
unit-tests:
build:
context: .
target: test
command: npm run test:unit
volumes:
- .:/app
- /app/node_modules
environment:
NODE_ENV: test
networks:
- test-network
# 集成测试
integration-tests:
build:
context: .
target: test
command: npm run test:integration
volumes:
- .:/app
- /app/node_modules
environment:
NODE_ENV: test
DATABASE_URL: postgresql://test:test123@test-db:5432/test_db
networks:
- test-network
depends_on:
- test-db
# E2E测试
e2e-tests:
build:
context: .
target: test
command: npm run test:e2e
volumes:
- .:/app
- /app/node_modules
environment:
NODE_ENV: test
APP_URL: http://app:3000
networks:
- test-network
depends_on:
- app
- test-db
# 应用实例(用于E2E测试)
app:
build:
context: .
target: production
environment:
NODE_ENV: test
DATABASE_URL: postgresql://test:test123@test-db:5432/test_db
networks:
- test-network
depends_on:
- test-db
networks:
test-network:
driver: bridge
🔧 调试和故障排除
1. 常见问题诊断
bash
# 查看服务状态
docker-compose ps
docker-compose ps --services
# 查看服务日志
docker-compose logs
docker-compose logs -f web
docker-compose logs --tail=100 db
# 查看网络配置
docker-compose config
docker-compose config --services
docker-compose config --volumes
# 验证配置文件
docker-compose config --quiet # 只验证,不输出
# 查看容器详细信息
docker-compose exec web env
docker-compose exec web ps aux
docker-compose exec web netstat -tulpn
2. 调试脚本
bash
#!/bin/bash
# compose-debug.sh
PROJECT_NAME=${1:-$(basename $(pwd))}
echo "🔍 Docker Compose调试工具"
echo "项目: $PROJECT_NAME"
echo "=========================="
echo ""
echo "📋 服务状态:"
docker-compose ps
echo ""
echo "🌐 网络信息:"
docker network ls --filter name=${PROJECT_NAME}
echo ""
echo "💾 数据卷信息:"
docker volume ls --filter name=${PROJECT_NAME}
echo ""
echo "📊 资源使用:"
docker stats --no-stream $(docker-compose ps -q) 2>/dev/null
echo ""
echo "🔍 健康检查:"
for container in $(docker-compose ps -q); do
name=$(docker inspect $container --format "{{.Name}}" | sed 's/\///')
health=$(docker inspect $container --format "{{.State.Health.Status}}" 2>/dev/null)
if [ "$health" != "" ]; then
echo " $name: $health"
else
echo " $name: 无健康检查"
fi
done
echo ""
echo "⚠️ 错误检查:"
# 检查是否有退出的容器
exited=$(docker-compose ps --filter status=exited -q)
if [ ! -z "$exited" ]; then
echo "发现退出的容器:"
docker-compose ps --filter status=exited
else
echo "✅ 所有容器正常运行"
fi
echo ""
echo "📝 最近日志:"
docker-compose logs --tail=10
3. 性能监控
bash
#!/bin/bash
# compose-monitor.sh
echo "📊 Docker Compose性能监控"
echo "=========================="
# 实时监控
while true; do
clear
echo "监控时间: $(date)"
echo ""
echo "🏃 运行状态:"
docker-compose ps --format "table {{.Name}}\t{{.State}}\t{{.Ports}}"
echo ""
echo "📈 资源使用:"
docker stats --no-stream --format \
"table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}" \
$(docker-compose ps -q) 2>/dev/null
echo ""
echo "💾 存储使用:"
docker system df
sleep 5
done
📋 最佳实践
1. 配置文件组织
bash
# 项目结构建议
project/
├── docker-compose.yml # 基础配置
├── docker-compose.override.yml # 开发环境覆盖
├── docker-compose.prod.yml # 生产环境配置
├── docker-compose.test.yml # 测试环境配置
├── .env # 默认环境变量
├── .env.example # 环境变量模板
├── .env.production # 生产环境变量
└── compose/ # 配置文件目录
├── nginx/
│ └── nginx.conf
├── postgres/
│ └── init.sql
└── scripts/
├── backup.sh
└── restore.sh
2. 安全最佳实践
yaml
# 安全配置示例
version: '3.8'
services:
web:
build: .
user: "1000:1000" # 非root用户
read_only: true # 只读根文件系统
tmpfs:
- /tmp
- /var/cache
cap_drop:
- ALL # 删除所有能力
cap_add:
- NET_BIND_SERVICE # 只添加必要能力
security_opt:
- no-new-privileges:true # 禁止提权
secrets:
- db_password # 使用secrets管理敏感信息
secrets:
db_password:
file: ./secrets/db_password.txt
3. 生产环境配置
yaml
# docker-compose.prod.yml
version: '3.8'
services:
web:
image: ${REGISTRY}/myapp:${TAG}
deploy:
replicas: 3
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
📝 下一步
现在您已经掌握了Docker Compose,接下来学习:
- Docker多阶段构建 - 掌握高级构建技巧
- Docker安全最佳实践 - 学习安全配置
🎯 本章要点
- ✅ 理解Docker Compose的核心概念和工作原理
- ✅ 掌握docker-compose.yml文件的编写技巧
- ✅ 学会多环境配置和服务编排
- ✅ 了解扩缩容和服务管理机制
- ✅ 掌握调试、监控和最佳实践
继续深入学习Docker高级特性!🐳