前言

在微服务架构盛行的今天,应用往往由多个服务组件组成——Web应用、数据库、缓存、消息队列等。如何优雅地管理和部署这些多容器应用?Docker Compose就是为此而生的解决方案。

作为Docker官方的容器编排工具,Docker Compose让开发者能够通过一个简单的YAML文件定义和运行多容器Docker应用。本文将通过完整的实战案例,带你从零开始掌握Docker Compose的核心能力。

1. Docker Compose核心概念

1.1 什么是Docker Compose?

Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。它通过一个docker-compose.yml配置文件来描述应用的服务、网络和数据卷,然后通过一个命令启动整个应用。

核心优势:

  • 简化多容器应用的管理
  • 一致的开发、测试和生产环境
  • 声明式的配置管理
  • 快速的启动和停止

1.2 核心组件解析

服务(Services)

服务是应用的一个容器实例。例如,一个Web应用可能有:

  • web:前端服务
  • api:后端API服务
  • db:数据库服务
  • cache:缓存服务

网络(Networks)

服务之间需要通信,Docker Compose自动创建默认网络,也可以自定义网络配置:

  • bridge:默认桥接网络
  • overlay:跨主机网络
  • internal:内部网络,不能与外部通信

数据卷(Volumes)

数据持久化的关键,分为:

  • named volumes:命名卷,Docker管理
  • bind mounts:绑定挂载,主机路径映射
  • tmpfs:临时文件系统

2. 快速入门:第一个Docker Compose项目

2.1 项目结构

1
2
3
4
5
6
7
8
9
10
11
my-app/
├── docker-compose.yml
├── web/
│ ├── Dockerfile
│ ├── index.html
│ └── nginx.conf
├── api/
│ ├── Dockerfile
│ ├── app.py
│ └── requirements.txt
└── README.md

2.2 定义Web服务

创建web/Dockerfile

1
2
3
4
5
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

创建web/index.html

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<title>Multi-Container App</title>
</head>
<body>
<h1>Hello from Docker Compose!</h1>
<p>This is the web service.</p>
</body>
</html>

2.3 定义API服务

创建api/Dockerfile

1
2
3
4
5
6
7
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]

创建api/requirements.txt

1
2
Flask==2.0.1
gunicorn==20.1.0

创建api/app.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from flask import Flask, jsonify
import os

app = Flask(__name__)

@app.route('/')
def hello():
return jsonify({
'message': 'Hello from Docker Compose API!',
'service': 'api',
'hostname': os.uname()[1]
})

@app.route('/health')
def health():
return jsonify({'status': 'healthy'})

if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

2.4 定义Docker Compose配置

创建docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '3.8'

services:
web:
build: ./web
ports:
- "8080:80"
depends_on:
- api
networks:
- app-network

api:
build: ./api
ports:
- "5000:5000"
networks:
- app-network

networks:
app-network:
driver: bridge

2.5 启动应用

1
2
3
4
5
6
7
8
9
10
11
# 构建并启动所有服务
docker-compose up -d

# 查看运行状态
docker-compose ps

# 查看日志
docker-compose logs -f api

# 停止并删除
docker-compose down

3. 进阶配置详解

3.1 服务配置优化

环境变量配置

1
2
3
4
5
6
7
services:
api:
environment:
- FLASK_ENV=production
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
env_file:
- ./.env

健康检查

1
2
3
4
5
6
7
8
services:
api:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s

资源限制

1
2
3
4
5
6
7
8
9
10
services:
api:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M

3.2 数据持久化配置

命名卷

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass

volumes:
postgres_data:
driver: local

绑定挂载

1
2
3
4
5
services:
web:
volumes:
- ./web/static:/usr/share/nginx/html/static
- ./logs:/var/log/nginx

3.3 网络配置

自定义网络

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '3.8'

services:
web:
networks:
- frontend
- backend

api:
networks:
- backend

db:
networks:
- backend

networks:
frontend:
driver: bridge

backend:
driver: bridge

网络别名

1
2
3
4
5
6
7
services:
db:
networks:
backend:
aliases:
- database
- postgres

3.4 多环境配置

开发环境(.env.dev):

1
2
3
4
5
6
7
8
9
10
version: '3.8'

services:
api:
build:
context: ./api
dockerfile: Dockerfile.dev
environment:
- DEBUG=true
- LOG_LEVEL=DEBUG

生产环境(.env.prod):

1
2
3
4
5
6
7
8
9
10
11
12
version: '3.8'

services:
api:
build:
context: ./api
dockerfile: Dockerfile.prod
environment:
- DEBUG=false
- LOG_LEVEL=INFO
deploy:
replicas: 3

4. 完整实战案例:电商平台架构

4.1 项目架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ecommerce-platform/
├── docker-compose.yml
├── docker-compose.prod.yml
├── frontend/
│ ├── Dockerfile
│ ├── package.json
│ └── public/
├── backend/
│ ├── Dockerfile
│ ├── src/
│ ├── requirements.txt
│ └── manage.py
├── database/
│ ├── init/
│ └── Dockerfile
├── redis/
│ └── Dockerfile
├── nginx/
│ ├── Dockerfile
│ └── nginx.conf
└── kafka/
├── Dockerfile
└── config/

4.2 前端服务

frontend/Dockerfile

1
2
3
4
5
6
7
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

4.3 后端服务

backend/Dockerfile

1
2
3
4
5
6
7
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "myapp.wsgi:application", "--bind", "0.0.0.0:8000"]

backend/requirements.txt

1
2
3
4
5
Django==4.0
gunicorn==20.1.0
psycopg2-binary==2.9.1
redis==4.0.2
kafka-python==2.0.2

4.4 数据库服务

database/Dockerfile

1
2
3
4
5
FROM postgres:13
COPY init/ /docker-entrypoint-initdb.d/
ENV POSTGRES_DB=ecommerce
ENV POSTGRES_USER=admin
ENV POSTGRES_PASSWORD=password123

4.5 缓存服务

redis/Dockerfile

1
2
3
FROM redis:6-alpine
COPY redis.conf /usr/local/etc/redis/redis.conf
CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]

redis/redis.conf

1
2
maxmemory 256mb
maxmemory-policy allkeys-lru

4.6 消息队列服务

kafka/Dockerfile

1
2
FROM confluentinc/cp-kafka:7.0.1
COPY config/server.properties /etc/kafka/server.properties

4.7 反向代理服务

nginx/Dockerfile

1
2
3
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf

nginx/nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
events {
worker_connections 1024;
}

http {
upstream frontend {
server frontend:3000;
}

upstream backend {
server backend:8000;
}

server {
listen 80;

location / {
proxy_pass http://frontend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

location /api {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}

4.8 完整的docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
version: '3.8'

services:
frontend:
build: ./frontend
ports:
- "3000:3000"
depends_on:
- backend
networks:
- app-network
environment:
- REACT_APP_API_URL=http://localhost:8000/api

backend:
build: ./backend
ports:
- "8000:8000"
depends_on:
- db
- redis
- kafka
networks:
- app-network
environment:
- DATABASE_URL=postgresql://admin:password123@db:5432/ecommerce
- REDIS_URL=redis://redis:6379
- KAFKA_BOOTSTRAP_SERVERS=kafka:9092
volumes:
- ./backend/logs:/app/logs

db:
build: ./database
ports:
- "5432:5432"
networks:
- app-network
volumes:
- postgres_data:/var/lib/postgresql/data

redis:
build: ./redis
ports:
- "6379:6379"
networks:
- app-network
volumes:
- redis_data:/data

kafka:
build: ./kafka
ports:
- "9092:9092"
networks:
- app-network
volumes:
- kafka_data:/var/lib/kafka

nginx:
build: ./nginx
ports:
- "80:80"
depends_on:
- frontend
- backend
networks:
- app-network

networks:
app-network:
driver: bridge

volumes:
postgres_data:
driver: local

redis_data:
driver: local

kafka_data:
driver: local

5. 生产环境部署最佳实践

5.1 多环境配置

开发环境配置(.env.dev):

1
2
3
4
5
6
7
8
9
10
11
version: '3.8'

services:
backend:
environment:
- DEBUG=true
- LOG_LEVEL=DEBUG

db:
environment:
- POSTGRES_HOST_AUTH_METHOD=trust

生产环境配置(docker-compose.prod.yml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3.8'

services:
backend:
deploy:
replicas: 3
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M

frontend:
deploy:
replicas: 2

nginx:
deploy:
replicas: 2
placement:
constraints:
- node.role == manager

5.2 安全配置

用户权限

1
2
3
4
5
services:
backend:
user: "1000:1000"
volumes:
- ./backend:/app:ro

私有镜像

1
2
3
4
5
6
7
8
9
10
11
12
services:
backend:
image: myregistry.com/myapp/backend:latest
secrets:
- db_credentials
- api_key

secrets:
db_credentials:
file: ./secrets/db_credentials.txt
api_key:
file: ./secrets/api_key.txt

5.3 监控与日志

日志配置

1
2
3
4
5
6
7
services:
backend:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

健康检查

1
2
3
4
5
6
7
8
services:
backend:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s

6. 常见问题与解决方案

6.1 网络连接问题

问题: 服务间无法通信

1
2
3
4
5
6
# 查看网络配置
docker network ls
docker network inspect app-network

# 测试连通性
docker exec -it backend_container ping db

解决方案:

  • 确保服务在同一网络中
  • 检查防火墙设置
  • 使用正确的服务名称

6.2 数据卷挂载问题

问题: 数据持久化失败

1
2
3
4
5
6
# 查看卷状态
docker volume ls
docker volume inspect postgres_data

# 手动挂载测试
docker run -it --rm -v postgres_data:/data busybox ls /data

解决方案:

  • 检查卷权限
  • 确认主机路径存在
  • 使用绝对路径

6.3 资源限制问题

问题: 容器资源不足

1
2
3
4
5
6
7
8
9
10
11
# 查看资源使用
docker stats

# 调整资源限制
services:
backend:
deploy:
resources:
limits:
memory: 2G
cpus: '2.0'

7. 性能优化技巧

7.1 构建优化

多阶段构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 开发环境
FROM node:16-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]

# 生产环境
FROM node:16-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm install --only=production
COPY --from=development /app ./
CMD ["npm", "start"]

缓存优化

1
2
3
4
5
6
7
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile.prod
args:
- NODE_ENV=production

7.2 运行时优化

并发处理

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
backend:
deploy:
replicas: 3
update_config:
parallelism: 2
delay: 10s
failure_action: continue
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s

负载均衡

1
2
3
4
5
6
services:
backend:
deploy:
mode: replicated
replicas: 3
endpoint_mode: vip

8. 自动化部署脚本

8.1 开发环境启动脚本

start-dev.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

set -e

echo "Starting development environment..."

# 创建网络
docker network create app-network 2>/dev/null || true

# 启动服务
docker-compose -f docker-compose.dev.yml up -d

echo "Development environment started successfully!"
echo "Frontend: http://localhost:3000"
echo "Backend: http://localhost:8000"
echo "Database: localhost:5432"

8.2 生产环境部署脚本

deploy.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash

set -e

ENV=${1:-production}
COMPOSE_FILE="docker-compose.${ENV}.yml"

echo "Deploying to ${ENV} environment..."

# 构建镜像
docker-compose -f $COMPOSE_FILE build

# 停止旧服务
docker-compose -f $COMPOSE_FILE down

# 启动新服务
docker-compose -f $COMPOSE_FILE up -d

# 健康检查
sleep 30
if curl -f http://localhost/health > /dev/null 2>&1; then
echo "Deployment successful!"
else
echo "Deployment failed!"
exit 1
fi

8.3 清理脚本

cleanup.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash

echo "Cleaning up Docker resources..."

# 停止所有容器
docker-compose down -v

# 删除镜像
docker images | grep "ecommerce" | awk '{print $3}' | xargs docker rmi -f

# 删除卷
docker volume ls | grep "ecommerce" | awk '{print $2}' | xargs docker volume rm

# 清理网络
docker network prune -f

echo "Cleanup completed!"

9. 总结

Docker Compose是管理多容器应用的利器,通过本文的实战学习,你掌握了:

  1. 基础概念:服务、网络、数据卷三大核心组件
  2. 配置管理:通过YAML文件定义复杂的容器编排
  3. 实战案例:构建完整的电商平台多容器架构
  4. 生产部署:环境隔离、安全配置、监控日志
  5. 性能优化:构建优化、运行时调优、自动化脚本

最佳实践建议:

  • 使用.env文件管理环境变量
  • 为不同环境创建不同的compose文件
  • 定期更新镜像和依赖包
  • 实施完善的监控和日志策略
  • 保持Docker Compose版本更新

掌握Docker Compose,你就能轻松驾驭现代微服务架构,实现高效的应用部署和管理。随着容器化技术的不断发展,Docker Compose依然是入门和进阶的重要工具,值得深入学习和实践。