Docker Compose 实战——用 YAML 编排多容器应用

Docker Compose 实战——用 YAML 编排多容器应用

作者: CaoZH
日期: 2023-06-15
本文为原创教程


学会了 Docker 基础后,下一个问题是:如果我的应用依赖 MySQL、Redis、Nginx 等多个服务怎么办?

手动一个一个 docker run 显然不现实。Docker Compose 就是来解决这个问题的——用一个 YAML 文件定义和运行多容器应用。

一、Docker Compose 是什么?

Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。你只需编写一个 docker-compose.yml 文件,然后一条命令就能启动所有服务。

核心优势

手动方式 Docker Compose
写多个 docker run 命令 一个 docker-compose.yml
需要记住端口映射 声明式配置
容器启动顺序需手动控制 depends_on 自动控制
网络连接复杂 自动创建共享网络

二、安装 Docker Compose

1
2
3
4
5
6
# Linux 安装
sudo curl -L "https://github.com/docker/compose/releases/download/v2.15.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# 验证
docker-compose --version

Docker Desktop for Mac/Windows 已内置 Compose,无需单独安装。

三、核心概念

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'          # Compose 文件版本

services: # 定义各个容器服务
web: # 服务名称
build: . # 构建上下文
ports: # 端口映射
- "8080:80"
volumes: # 数据卷
- ./html:/usr/share/nginx/html
depends_on: # 依赖关系
- db

db: # 另一个服务
image: mysql:8.0
environment: # 环境变量
MYSQL_ROOT_PASSWORD: root123

volumes: # 命名卷
mysql-data:

networks: # 自定义网络
app-net:

四、实战:搭建 Spring Boot + MySQL + Redis

项目结构

1
2
3
4
5
6
7
8
9
10
myapp/
├── docker-compose.yml
├── app/
│ ├── Dockerfile
│ └── target/
│ └── myapp.jar
├── mysql/
│ └── init.sql
└── nginx/
└── default.conf

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
version: '3.8'

services:
# MySQL 数据库
mysql:
image: mysql:8.0
container_name: myapp-mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: myapp
MYSQL_USER: appuser
MYSQL_PASSWORD: app123
volumes:
- mysql-data:/var/lib/mysql
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
networks:
- app-net

# Redis 缓存
redis:
image: redis:7-alpine
container_name: myapp-redis
restart: always
ports:
- "6379:6379"
volumes:
- redis-data:/data
command: redis-server --appendonly yes --requirepass redis123
networks:
- app-net

# Spring Boot 应用
app:
build: ./app
container_name: myapp-app
restart: always
ports:
- "8080:8080"
depends_on:
- mysql
- redis
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/myapp?useSSL=false&serverTimezone=Asia/Shanghai
SPRING_DATASOURCE_USERNAME: appuser
SPRING_DATASOURCE_PASSWORD: app123
SPRING_REDIS_HOST: redis
SPRING_REDIS_PASSWORD: redis123
volumes:
- app-logs:/app/logs
networks:
- app-net

# Nginx 反向代理
nginx:
image: nginx:alpine
container_name: myapp-nginx
restart: always
ports:
- "80:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- app-net

volumes:
mysql-data:
redis-data:
app-logs:

networks:
app-net:
driver: bridge

Nginx 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# nginx/default.conf
upstream app-backend {
server app:8080;
}

server {
listen 80;
server_name example.com;

location / {
proxy_pass http://app-backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

location /api/ {
proxy_pass http://app-backend;
proxy_set_header Host $host;
}
}

Spring Boot Dockerfile

1
2
3
4
5
6
7
8
9
10
# app/Dockerfile
FROM openjdk:8-jre-alpine

WORKDIR /app

COPY target/myapp.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

五、常用 Compose 命令

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
# 启动所有服务
docker-compose up -d

# 查看运行状态
docker-compose ps

# 查看日志
docker-compose logs -f
docker-compose logs -f app # 只看某个服务

# 停止服务
docker-compose stop

# 停止并删除容器
docker-compose down

# 停止并删除容器 + 数据卷
docker-compose down -v

# 重新构建并启动
docker-compose up -d --build

# 执行命令
docker-compose exec app bash
docker-compose exec mysql mysql -u root -p

六、多环境配置

1
2
3
4
5
6
7
8
9
# docker-compose.override.yml(开发环境覆盖)
services:
app:
ports:
- "8080:8080"
- "5005:5005" # JDWP 调试端口
environment:
SPRING_PROFILES_ACTIVE: dev
JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# docker-compose.prod.yml(生产环境)
version: '3.8'

services:
app:
restart: always
deploy:
replicas: 2
resources:
limits:
memory: 512M

nginx:
ports:
- "443:443"
volumes:
- ./nginx/ssl:/etc/nginx/ssl
- ./nginx/prod.conf:/etc/nginx/conf.d/default.conf
1
2
# 使用指定配置文件
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

七、总结

通过本教程,你学会了:

  • ✅ 编写 docker-compose.yml 编排多容器
  • ✅ 搭建 Spring Boot + MySQL + Redis + Nginx 完整环境
  • ✅ 使用 Compose 常用命令管理服务
  • ✅ 多环境配置分离
  • ✅ 持久化数据卷管理

Docker Compose 是目前最实用的容器编排工具,日常开发、小团队部署完全够用。对于大规模集群,下一步可以学习 Kubernetes(K8s)。


首发于 CaoZH 的笔记