Docker Compose:把多个容器组织成一个应用
Docker Compose:把多个容器组织成一个应用
一个 SpringBoot 应用通常不会单独运行。它依赖 MySQL 存数据,依赖 Redis 做缓存,有的还依赖 RabbitMQ、Elasticsearch 等中间件。上一篇讲了如何把单个应用装进容器,但实际开发中你需要同时启动这一整套服务。
用 docker run 逐个启动显然不太方便。Docker Compose 提供了一种更适合多服务应用的管理方式。一个 YAML 文件描述所有服务及其依赖关系,一条命令全部启动。
目录
- 从单个容器到完整应用环境
- Compose 和 docker run 的关系
- Compose 如何描述一个应用环境
- 用 Compose 编排 SpringBoot + MySQL + Redis
- 服务通信:容器之间如何通过服务名访问
- 服务启动依赖与健康检查
- 开发环境中的 Compose 常用操作
- 总结
从单个容器到完整应用环境
一个典型的 SpringBoot 开发环境,至少需要这几个服务同时运行:
SpringBoot 应用
│
├── MySQL 存储业务数据
├── Redis 缓存和会话管理
└── RabbitMQ 消息队列(可选)
手动启动这些服务,大致是这样的流程:
# 启动 MySQL
docker run -d --name mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=root123 \
-e MYSQL_DATABASE=myapp \
-v mysql-data:/var/lib/mysql \
mysql:8.0
# 启动 Redis
docker run -d --name redis \
-p 6379:6379 \
redis:7
# 启动应用
docker run -d --name my-app \
-p 8080:8080 \
-e SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/myapp \
-e SPRING_REDIS_HOST=redis \
my-app:1.0
真正麻烦的是配置分散在命令参数中,难以维护和复用。每次修改配置要删掉容器重新创建,换台机器又要全部重来。服务之间的启动顺序、网络连接、环境变量配置都靠人记住,出错了排查也麻烦。
Compose 和 docker run 的关系
上一篇用 docker run 启动单个容器,这篇用 Compose 管理多个容器。两者不是替代关系,而是适用场景不同。
docker run 适合一次性操作——快速测试一个镜像、临时跑个工具容器、调试某个服务。它的问题是每条命令只管一个容器,多个服务之间的配置全靠命令参数传递,没有统一的声明文件。
docker compose 适合需要多个服务协作的场景——开发环境、集成测试、本地 demo。它的核心价值是把所有服务的配置集中到一个 YAML 文件中,用一条命令管理整个应用环境。
| docker run | docker compose | |
|---|---|---|
| 管理范围 | 单个容器 | 多个服务 |
| 配置方式 | 命令参数 | YAML 文件 |
| 网络 | 需手动创建和连接 | 自动创建共享网络 |
| 启动顺序 | 不支持 | depends_on |
| 适用场景 | 临时测试、单服务 | 开发环境、多服务编排 |
日常开发中,两者经常配合使用。用 docker run 快速验证镜像是否能跑,确认没问题后再写进 docker-compose.yml。
Compose 如何描述一个应用环境
Compose 用一个 YAML 文件定义所有服务。核心结构:
services:
服务名:
image: 镜像名
ports:
- "宿主机端口:容器端口"
environment:
- 环境变量=值
volumes:
- 卷名:容器内路径
几个关键字段:
- services:定义所有服务,每个服务是一个独立的容器
- image:指定使用的镜像。也可以用
build指向 Dockerfile,让 Compose 自己构建 - ports:端口映射,和
docker run -p等价 - environment:环境变量,和
docker run -e等价 - volumes:数据持久化,和
docker run -v等价
Compose 文件不需要记命令参数,所有配置都在一个文件里,版本管理也方便。
用 Compose 编排 SpringBoot + MySQL + Redis
把前面手动启动的三个服务用 Compose 编排:
services:
mysql:
image: mysql:8.0
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: myapp
volumes:
- mysql-data:/var/lib/mysql
redis:
image: redis:7
ports:
- "6379:6379"
command: redis-server --requirepass redis123
my-app:
image: my-app:1.0
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/myapp
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root123
SPRING_REDIS_HOST: redis
SPRING_REDIS_PASSWORD: redis123
depends_on:
- mysql
- redis
volumes:
mysql-data:
把这个文件保存为 docker-compose.yml,在同目录下执行:
docker compose up -d
三个服务同时启动。docker compose down 停止并删除所有容器。
Redis 通过 command 覆盖了默认启动命令,加上了密码认证。即使是开发环境,也不建议跑无密码的 Redis——配置泄露时没有密码就是裸奔。
注意 environment 中数据库连接地址写的是 mysql:3306,不是 localhost:3306。这是因为 Compose 会自动创建一个网络,所有服务都在这个网络中,可以直接用服务名互相访问。
服务通信:容器之间如何通过服务名访问
手动 docker run 时,如果不在同一个 Docker 网络中,容器之间是无法用名称通信的。Compose 会自动创建网络,并将所有服务加入同一个网络。
在这个网络中,每个服务名就是它的主机名。my-app 连接 MySQL 时,地址写 mysql:3306 就能连上,不需要知道 MySQL 容器的实际 IP。

这也是为什么 application.yml 中的 localhost 在容器内不生效:容器内的 localhost 指向容器自己,不是宿主机,也不是其他容器。用 Compose 编排时,所有依赖服务的地址都应该写服务名。
服务启动依赖与健康检查
depends_on 只保证启动顺序,不保证服务就绪。MySQL 容器启动后,还需要几秒钟初始化数据库。如果应用在这几秒内尝试连接,会报连接失败。
my-app:
depends_on:
- mysql
- redis
上面的配置只保证 MySQL 容器先启动,但不保证 MySQL 已经准备好接受连接。
要等服务真正就绪,需要配合健康检查:
mysql:
image: mysql:8.0
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: myapp
volumes:
- mysql-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 10
my-app:
image: my-app:1.0
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/myapp
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root123
SPRING_REDIS_HOST: redis
SPRING_REDIS_PASSWORD: redis123
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_started
healthcheck 通过 mysqladmin ping 检测 MySQL 是否就绪。depends_on 配合 condition: service_healthy,Compose 会根据健康检查状态决定是否启动依赖服务后的容器。
Redis 启动很快,用 service_started 就够了。MySQL 和 PostgreSQL 这类需要初始化的服务,建议都加健康检查。
开发环境中的 Compose 常用操作
# 启动所有服务(后台运行)
docker compose up -d
# 查看运行状态
docker compose ps
# 查看某个服务的日志
docker compose logs my-app
# 实时跟踪日志
docker compose logs -f my-app
# 停止所有服务
docker compose down
# 停止并删除数据卷(慎用,会清掉数据库数据)
docker compose down -v
# 重新构建某个服务的镜像
docker compose build my-app
# 重启某个服务
docker compose restart my-app
开发中最常用的组合是 docker compose up -d 启动,docker compose logs -f my-app 跟踪应用日志,docker compose down 停止。
如果修改了 docker-compose.yml,需要重新执行 docker compose up -d,Compose 会自动检测变化并重建受影响的容器。
总结
Docker Compose 把多个服务的启动、配置和网络连接集中到一个 YAML 文件中。docker compose up -d 一条命令启动整套环境,docker compose down 一条命令全部停止。
Compose 自动创建网络,容器间用服务名互相访问,不需要手动配置 IP。depends_on 配合 healthcheck 可以控制服务启动顺序,确保依赖服务就绪后再启动应用。
更多推荐
所有评论(0)