Docker Compose一键启动微服务集群:别再手动敲命令了
networks:services:mysql:networks:api:networks:所有服务加入同一个自定义网络后,它们之间可以用服务名互相访问。比如api服务里配置,就能直接连到MySQL容器。千万别用--link,那个已经被废弃了。git pulldocker-compose ps # 检查服务状态三行命令。之前要搞半天的活,现在几秒钟搞定。而且配置文件()本身就是文档,团队成员一看就
Docker Compose一键启动微服务集群:别再手动敲命令了
上周线上部署一个微服务项目,折腾了整整一下午。
三个服务:应用服务、数据库、Redis。正常操作应该是:先起数据库,等它ready,再起Redis,最后起应用服务。但我敲命令的时候手滑了一下,顺序搞反了,结果应用服务一直报连接失败。
查日志、重启、再查日志……搞了两个小时才发现启动顺序的问题。
那一刻我真的想抽自己——为什么不早点用Docker Compose?
今天聊聊怎么用Docker Compose一键启动微服务集群,省得像我一样折腾。
为什么要用Docker Compose?
先说说不用Docker Compose的痛苦。
假设你要启动一个简单的微服务集群:Nginx + 后端API + MySQL + Redis。手动部署的流程大概是这样的:
# 启动MySQL
docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-v mysql-data:/var/lib/mysql \
mysql:8.0
# 等MySQL启动……sleep 10秒(这招真的不靠谱)
# 启动Redis
docker run -d --name redis redis:7.0
# 启动后端服务
docker run -d --name api \
--link mysql \
--link redis \
-e DB_HOST=mysql \
-e REDIS_HOST=redis \
my-api:latest
# 启动Nginx
docker run -d -p 80:80 \
--link api \
-v /path/to/nginx.conf:/etc/nginx/nginx.conf \
nginx:latest
问题在哪?
- 启动顺序难控制——你不知道MySQL什么时候真的ready了,sleep是赌博
- 命令太长——敲错一个字母就重来
- 网络配置麻烦——
--link已经被废弃了,现在得自己搞network - 没有统一入口——重启、停止、查看日志得分开操作每个容器
Docker Compose解决的正是这些问题。
一个完整的docker-compose.yml
这是我那个项目的配置文件,拿出来给你参考:
version: '3.8'
services:
# MySQL数据库
mysql:
image: mysql:8.0
container_name: project-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: appdb
TZ: Asia/Shanghai
volumes:
- mysql-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p123456"]
interval: 5s
timeout: 10s
retries: 5
networks:
- app-network
# Redis缓存
redis:
image: redis:7.0-alpine
container_name: project-redis
restart: always
command: redis-server --appendonly yes
volumes:
- redis-data:/data
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 3
networks:
- app-network
# 后端API服务
api:
build:
context: ./api
dockerfile: Dockerfile
container_name: project-api
restart: always
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
environment:
DB_HOST: mysql
DB_PORT: 3306
DB_USER: root
DB_PASSWORD: 123456
REDIS_HOST: redis
REDIS_PORT: 6379
ports:
- "8000:8000"
networks:
- app-network
# Nginx反向代理
nginx:
image: nginx:latest
container_name: project-nginx
restart: always
depends_on:
- api
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/logs:/var/log/nginx
ports:
- "80:80"
networks:
- app-network
# 数据卷
volumes:
mysql-data:
driver: local
redis-data:
driver: local
# 自定义网络
networks:
app-network:
driver: bridge
一行命令启动所有服务:
docker-compose up -d
搞定。就这四个字,代替了我之前敲的那几十行命令。
关键配置详解
让我挑几个最重要的配置说说。
1. 健康检查——避免连接失败
这是最关键的配置,也是我之前踩坑的地方。
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p123456"]
interval: 5s
timeout: 10s
retries: 5
test 定义了健康检查命令。对于MySQL,用mysqladmin ping;对于Redis,用redis-cli ping;对于HTTP服务,用curl或wget。
interval 是检查间隔,每5秒检查一次。
timeout 是单次检查超时时间,10秒没响应就当失败。
retries 是重试次数,连续失败5次才判定为不健康。
配合 depends_on 的 condition: service_healthy,就能确保依赖服务真正ready后才启动。
2. 服务依赖——控制启动顺序
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
这个配置的意思是:api 服务必须等待 mysql 和 redis 都健康检查通过后才能启动。
注意:不要只用短格式的 depends_on: [mysql, redis],那只保证容器启动,不保证服务ready。我吃过这个亏,应用启动时数据库还在初始化,结果连接失败。
3. 自定义网络——容器间通信
networks:
app-network:
driver: bridge
services:
mysql:
networks:
- app-network
api:
networks:
- app-network
所有服务加入同一个自定义网络后,它们之间可以用服务名互相访问。比如 api 服务里配置 DB_HOST=mysql,就能直接连到MySQL容器。
千万别用 --link,那个已经被废弃了。
4. 数据卷——数据持久化
volumes:
- mysql-data:/var/lib/mysql # 命名卷
- ./init.sql:/docker-entrypoint-initdb.d/init.sql # 挂载文件
volumes:
mysql-data:
driver: local
命名卷(mysql-data)由Docker管理,好处是:
- 路径不依赖宿主机,可移植性好
- 删除容器后数据不会丢
绑定挂载(./init.sql:...)直接映射宿主机文件,适合配置文件和初始化脚本。
实战操作技巧
启动和停止
# 启动所有服务(后台运行)
docker-compose up -d
# 启动单个服务
docker-compose up -d mysql
# 停止所有服务
docker-compose stop
# 停止并删除容器
docker-compose down
# 停止并删除容器+数据卷(慎用!数据会丢)
docker-compose down -v
查看日志
# 查看所有服务日志
docker-compose logs
# 实时追踪日志(tail -f效果)
docker-compose logs -f
# 只看某个服务的日志
docker-compose logs -f api
# 查看最近100行
docker-compose logs --tail=100
进入容器调试
# 进入api容器
docker-compose exec api bash
# 进入MySQL容器执行SQL
docker-compose exec mysql mysql -uroot -p123456
重建服务
# 修改了Dockerfile或依赖,需要重建
docker-compose up -d --build api
# 强制重建(不使用缓存)
docker-compose up -d --build --force-recreate
踩坑记录:血泪教训
坑1:健康检查命令写错了
# ❌ 错误:健康检查命令需要在容器内能执行
healthcheck:
test: ["CMD", "mysql", "-h", "localhost", "-e", "SELECT 1"]
# ✅ 正确:用mysqladmin ping
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p123456"]
如果你用的镜像没有 mysqladmin,就得换命令。有些镜像甚至没有 curl,健康检查得想办法绕过。
坑2:时区问题
容器默认用UTC时间,日志时间会跟实际差8小时。
# 加上时区环境变量
environment:
TZ: Asia/Shanghai
或者挂载宿主机的时区文件:
volumes:
- /etc/localtime:/etc/localtime:ro
坑3:权限问题
挂载目录时要注意权限,Nginx的日志目录如果属主不对,会写不进去。
# 启动前先创建目录并设置权限
mkdir -p ./nginx/logs
chown -R 101:101 ./nginx/logs # Nginx容器里的用户ID是101
或者用匿名卷让Docker自动处理权限:
volumes:
- nginx-logs:/var/log/nginx
坑4:服务名冲突
如果你有多个Docker Compose项目,服务名可能冲突。比如都有 mysql 容器,启动第二个项目时会报错。
解决方法是给容器加个唯一前缀:
services:
mysql:
container_name: project1-mysql # 加上项目名前缀
或者在不同的目录里运行Docker Compose,它会自动加目录名前缀。
写在最后
用了Docker Compose之后,我的部署流程变成了这样:
git pull
docker-compose up -d --build
docker-compose ps # 检查服务状态
三行命令。
之前要搞半天的活,现在几秒钟搞定。而且配置文件(docker-compose.yml)本身就是文档,团队成员一看就知道项目是怎么部署的。
当然,Docker Compose也有局限。如果你搞的是几十个服务的大规模集群,该用Kubernetes还得用K8s。但对于中小规模的微服务项目,尤其是开发测试环境,Docker Compose真的是性价比最高的方案。
别再手动敲 docker run 了,真的不酷。把你的部署流程写成 docker-compose.yml,一键启动,省下来的时间去干点有意义的事——比如陪家人,或者多写几行代码。
有问题欢迎评论区交流。如果这篇文章帮到了你,点个赞呗~
Docker官方文档:https://docs.docker.com/compose/
Docker Compose示例:https://github.com/docker/awesome-compose
更多推荐
所有评论(0)