Docker Compose 部署
Docker Compose 简介
核心概念
服务(Service):
- 应用的组件
- 可以是一个微服务、数据库、中间件等
- 支持多实例
网络(Network):
- 服务间通信的网络
- 支持自定义网络
- 服务发现
卷(Volume):
- 数据持久化
- 配置文件挂载
- 日志存储
配置(Config):
- 环境变量
- 配置文件
- 密钥管理
架构设计
┌─────────────────────────────────────────┐
│ docker-compose.yml │
│ ┌─────────────────────────────────┐ │
│ │ Services Definition │ │
│ │ - user-service │ │
│ │ - order-service │ │
│ │ - mysql │ │
│ │ - redis │ │
│ └─────────────────────────────────┘ │
└───────────────────┬─────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Docker Compose Engine │
└───────────────────┬─────────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ Container │ │ Container │ │ Container │
│ 1 │ │ 2 │ │ 3 │
└───────────┘ └───────────┘ └───────────┘
快速开始
1. 安装 Docker Compose
Linux:
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
macOS:
# Docker Desktop 已包含
docker-compose --version
Windows:
# Docker Desktop 已包含
docker-compose --version
2. 基础示例
微服务应用:
version: '3.8'
services:
user-service:
image: user-service:latest
ports:
- "8081:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- DB_HOST=mysql
- REDIS_HOST=redis
depends_on:
- mysql
- redis
networks:
- microservice-network
order-service:
image: order-service:latest
ports:
- "8082:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- DB_HOST=mysql
- REDIS_HOST=redis
depends_on:
- mysql
- redis
networks:
- microservice-network
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: microservice
volumes:
- mysql-data:/var/lib/mysql
networks:
- microservice-network
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
networks:
- microservice-network
networks:
microservice-network:
driver: bridge
volumes:
mysql-data:
redis-data:
3. 常用命令
# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
# 停止所有服务
docker-compose down
# 重启服务
docker-compose restart
# 重新构建并启动
docker-compose up -d --build
# 执行命令
docker-compose exec user-service bash
# 查看资源使用
docker-compose top
微服务部署
1. Spring Cloud 全家桶
version: '3.8'
services:
# 服务注册中心
nacos:
image: nacos/nacos-server:2.2.0
container_name: nacos
environment:
- MODE=standalone
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=mysql
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=nacos
- MYSQL_SERVICE_PASSWORD=nacos123
ports:
- "8848:8848"
- "9848:9848"
depends_on:
- mysql
networks:
- microservice-network
# 配置中心
sentinel:
image: bladex/sentinel-dashboard:1.8.6
container_name: sentinel
ports:
- "8080:8080"
environment:
- SENTINEL_USERNAME=sentinel
- SENTINEL_PASSWORD=sentinel
networks:
- microservice-network
# 网关
gateway:
image: gateway:latest
container_name: gateway
ports:
- "80:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- NACOS_SERVER_ADDR=nacos:8848
- SENTINEL_DASHBOARD_ADDR=sentinel:8080
depends_on:
- nacos
- sentinel
networks:
- microservice-network
# 用户服务
user-service:
image: user-service:latest
container_name: user-service
environment:
- SPRING_PROFILES_ACTIVE=docker
- NACOS_SERVER_ADDR=nacos:8848
depends_on:
- nacos
- mysql
- redis
networks:
- microservice-network
# 订单服务
order-service:
image: order-service:latest
container_name: order-service
environment:
- SPRING_PROFILES_ACTIVE=docker
- NACOS_SERVER_ADDR=nacos:8848
depends_on:
- nacos
- mysql
- redis
networks:
- microservice-network
# 数据库
mysql:
image: mysql:8.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: microservice
volumes:
- mysql-data:/var/lib/mysql
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- microservice-network
# Redis
redis:
image: redis:7-alpine
container_name: redis
command: redis-server --appendonly yes
volumes:
- redis-data:/data
networks:
- microservice-network
# 链路追踪
skywalking-oap:
image: apache/skywalking-oap-server:9.7.0
container_name: skywalking-oap
environment:
SW_STORAGE: elasticsearch
SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
depends_on:
- elasticsearch
networks:
- microservice-network
skywalking-ui:
image: apache/skywalking-ui:9.7.0
container_name: skywalking-ui
ports:
- "8088:8080"
environment:
SW_OAP_ADDRESS: skywalking-oap:12800
depends_on:
- skywalking-oap
networks:
- microservice-network
elasticsearch:
image: elasticsearch:7.17.0
container_name: elasticsearch
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- es-data:/usr/share/elasticsearch/data
networks:
- microservice-network
networks:
microservice-network:
driver: bridge
volumes:
mysql-data:
redis-data:
es-data:
2. 多环境配置
docker-compose.dev.yml:
version: '3.8'
services:
user-service:
build:
context: .
dockerfile: Dockerfile
environment:
- SPRING_PROFILES_ACTIVE=dev
- DEBUG_MODE=true
volumes:
- ./logs:/app/logs
order-service:
build:
context: ../order-service
dockerfile: Dockerfile
environment:
- SPRING_PROFILES_ACTIVE=dev
docker-compose.prod.yml:
version: '3.8'
services:
user-service:
image: registry.example.com/user-service:1.0.0
deploy:
replicas: 3
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 1G
environment:
- SPRING_PROFILES_ACTIVE=prod
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "3"
order-service:
image: registry.example.com/order-service:1.0.0
deploy:
replicas: 3
使用多环境:
# 开发环境
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# 生产环境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
3. 服务健康检查
version: '3.8'
services:
user-service:
image: user-service:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
mysql:
image: mysql:8.0
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot123"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
配置管理
1. 环境变量
.env 文件:
# 数据库配置
MYSQL_ROOT_PASSWORD=root123
MYSQL_DATABASE=microservice
MYSQL_USER=app
MYSQL_PASSWORD=app123
# Redis 配置
REDIS_PASSWORD=redis123
# 服务配置
SPRING_PROFILES_ACTIVE=docker
NACOS_SERVER_ADDR=nacos:8848
# 版本
USER_SERVICE_VERSION=1.0.0
ORDER_SERVICE_VERSION=1.0.0
使用环境变量:
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
user-service:
image: user-service:${USER_SERVICE_VERSION}
environment:
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE}
2. Config 文件
version: '3.8'
services:
user-service:
image: user-service:latest
configs:
- source: app-config
target: /app/config/application.yml
- source: logback-config
target: /app/config/logback.xml
configs:
app-config:
file: ./config/application.yml
logback-config:
file: ./config/logback.xml
3. Secrets 管理
version: '3.8'
services:
mysql:
image: mysql:8.0
secrets:
- mysql-root-password
- mysql-database
secrets:
mysql-root-password:
file: ./secrets/mysql-root-password.txt
mysql-database:
file: ./secrets/mysql-database.txt
网络配置
1. 自定义网络
version: '3.8'
services:
gateway:
networks:
- frontend
- backend
user-service:
networks:
- backend
order-service:
networks:
- backend
mysql:
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 内部网络,不暴露到外部
2. 服务发现
version: '3.8'
services:
user-service:
image: user-service:latest
networks:
microservice-network:
aliases:
- user
- user-service
order-service:
image: order-service:latest
networks:
microservice-network:
aliases:
- order
- order-service
networks:
microservice-network:
driver: bridge
日志管理
1. 日志驱动
version: '3.8'
services:
user-service:
image: user-service:latest
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "3"
compress: "true"
order-service:
image: order-service:latest
logging:
driver: "syslog"
options:
syslog-address: "udp://logserver:514"
2. 日志收集
version: '3.8'
services:
filebeat:
image: elastic/filebeat:8.8.0
container_name: filebeat
volumes:
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- microservice-network
depends_on:
- elasticsearch
elasticsearch:
image: elasticsearch:7.17.0
environment:
- discovery.type=single-node
volumes:
- es-data:/usr/share/elasticsearch/data
kibana:
image: kibana:7.17.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_URL=http://elasticsearch:9200
networks:
microservice-network:
driver: bridge
volumes:
es-data:
性能优化
1. 资源限制
version: '3.8'
services:
user-service:
image: user-service:latest
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 1G
mysql:
image: mysql:8.0
deploy:
resources:
limits:
cpus: '4'
memory: 4G
2. 构建优化
Dockerfile:
# 多阶段构建
FROM maven:3.8-openjdk-17 AS build
WORKDIR /app
COPY . .
RUN mvn clean package -DskipTests
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
docker-compose.yml:
version: '3.8'
services:
user-service:
build:
context: .
dockerfile: Dockerfile
args:
- MAVEN_OPTS=-Xmx2g
image: user-service:latest
3. 缓存优化
version: '3.8'
services:
user-service:
build:
context: .
cache_from:
- user-service:latest
- user-service:cache
image: user-service:latest
监控告警
1. Prometheus 监控
version: '3.8'
services:
prometheus:
image: prom/prometheus:v2.45.0
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
networks:
- microservice-network
grafana:
image: grafana/grafana:10.0.0
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
depends_on:
- prometheus
networks:
- microservice-network
node-exporter:
image: prom/node-exporter:v1.6.0
container_name: node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
networks:
- microservice-network
networks:
microservice-network:
driver: bridge
volumes:
prometheus-data:
grafana-data:
2. 告警规则
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'spring-boot'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['user-service:8080', 'order-service:8080']
- job_name: 'mysql'
static_configs:
- targets: ['mysql:3306']
- job_name: 'redis'
static_configs:
- targets: ['redis:6379']
最佳实践
1. 目录结构
docker/
├── docker-compose.yml
├── docker-compose.dev.yml
├── docker-compose.prod.yml
├── .env
├── config/
│ ├── application.yml
│ └── logback.xml
├── secrets/
│ ├── mysql-root-password.txt
│ └── redis-password.txt
├── mysql/
│ └── init.sql
└── logs/
2. CI/CD 集成
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build and push
run: |
docker build -t user-service:${{ github.sha }} .
docker push registry.example.com/user-service:${{ github.sha }}
- name: Deploy with docker-compose
run: |
docker-compose pull
docker-compose up -d
3. 备份恢复
#!/bin/bash
# backup.sh
# 备份 MySQL
docker-compose exec -T mysql mysqldump -u root -proot123 microservice > backup/mysql-$(date +%Y%m%d).sql
# 备份 Redis
docker-compose exec -T redis redis-cli SAVE
# 压缩备份
tar -czf backup/full-$(date +%Y%m%d).tar.gz backup/
# 清理旧备份
find backup/ -name "*.tar.gz" -mtime +7 -delete
总结
Docker Compose 是微服务本地开发和测试的理想选择,支持多容器应用编排、服务发现、配置管理等功能。
通过合理的配置和优化,可以快速搭建微服务开发环境,提高开发效率。
在生产环境中,建议结合 CI/CD、监控告警等工具,建立完善的部署和运维体系。