Docker Compose:用一个 yml 文件搞定本地开发环境

Docker Compose:用一个 yml 文件搞定本地开发环境

以前本地跑项目,要先开 MySQL,再开 Redis,偶尔还有 RabbitMQ——每次开机都要挨个确认哪个没起来,换台电脑还得重新装一遍。有了 Docker Compose 之后,一条命令全搞定。

一个真实的 docker-compose.yml

MySQL + Redis + RabbitMQ 三件套,大多数 Java 后端项目够用:

version: '3.8'

services:
mysql:
image: mysql:8.0
container_name: dev-mysql
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: myapp
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
networks:
- dev-net

redis:
image: redis:7.0
container_name: dev-redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- dev-net

rabbitmq:
image: rabbitmq:3.12-management
container_name: dev-rabbitmq
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: admin123
ports:
- "5672:5672"
- "15672:15672" # 管理后台
networks:
- dev-net

volumes:
mysql_data:
redis_data:

networks:
dev-net:
driver: bridge

常用命令:

docker-compose up -d           # 后台启动所有服务
docker-compose down # 停止并删除容器(数据不会丢,volume 还在)
docker-compose logs -f mysql # 实时查看 mysql 日志
docker-compose ps # 查看各服务当前状态

三个最值得注意的配置点

1. volumes 持久化

不加 volumes,容器删了数据就没了。上面配置里 mysql_data:/var/lib/mysql 的意思是:MySQL 的数据目录挂到 named volume mysql_data,容器删掉 volume 还在,下次 up 自动恢复。

两种挂载方式:

  • Named volumemysql_data:/var/lib/mysql):Docker 自己管路径,适合数据库
  • Bind mount./config:/etc/mysql/conf.d):挂到宿主机具体目录,适合需要直接编辑的配置文件

2. networks 网络配置

容器之间通信用服务名,不是 localhost

比如 Java 应用如果也在同一个 Compose 文件里,Redis 的连接地址应该写:

spring.redis.host=redis   # 服务名,不是 localhost

如果 Java 应用跑在 IDE 里(宿主机),连容器里的服务,写 127.0.0.1 即可,因为端口已经通过 ports 映射到宿主机了。

3. depends_on 依赖顺序

services:
app:
depends_on:
- mysql
- redis

depends_on 只保证 MySQL 容器启动了,不保证 MySQL 服务已就绪可以接受连接。MySQL 从容器启动到能接受连接通常需要十几秒,应用启动太快会报连接失败。

解决方式:Spring Boot 配置合理的连接重试,或者用 healthcheck + condition: service_healthy

mysql:
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 10

app:
depends_on:
mysql:
condition: service_healthy

一个典型坑:容器内的 localhost 不是你的电脑

第一次把 Java 应用也打进 Docker 时,配置文件里 MySQL 地址写的是 localhost:3306,结果一直连不上。

原因:在容器里,localhost 指的是容器自己,不是宿主机。MySQL 跑在另一个容器里,不在 localhost

连接地址的选择取决于部署方式:

场景应该用的地址
应用和依赖都在同一个 Compose 文件里服务名(mysql:3306
应用跑在宿主机 IDE,依赖在容器里127.0.0.1:3306(端口已映射到宿主机)
容器内需要访问宿主机host.docker.internal(Mac/Windows)或 docker0 网卡 IP(Linux)