Docker-compose编排微服务顺序启动
一、概述
docker-compose可以方便组合多个 docker 容器服务, 但是, 当容器服务之间存在依赖关系时, docker-compose 并不能保证服务的启动顺序。docker-compose 中的 depends_on 配置是容器的启动顺序, 并不是容器中服务的启动顺序。本章将详细叙述如何解决 docker-compose 顺序启动微服务的问题。
微服务清单
服务名 |
端口 |
服务说明 |
依赖服务 |
启动优先级 |
---|---|---|---|---|
eureka-service |
8761 |
服务注册与发现 |
--- |
1 |
auth-service |
8888 |
认证服务 |
eureka-service |
2 |
user-service |
8763 |
用户服务 |
eureka-service |
2 |
gateway-service |
8081 |
网关服务 |
eureka-service |
2 |
说明:eureka需要第一个启动,其他微服务必须等待eureka启动之后,才能启动。否则无法注册服务!
二、解决方案
针对这个问题,docker-compose官方给的建议是,通过wait-for-it.sh脚本来控制。
简单来说,这个脚本就是探测某个依赖的服务的tcp端口是否开放,否则一直等待,直到端口探测成功,才会启动后面的命令。
关于wait-for-it.sh的使用,请参考链接:
https://blog.csdn.net/wuzhong8809/article/details/82500722
环境说明
本文采用一台centos 7.6,通过docker-compose启动java spring cloud
ip地址:192.168.128.130
但是我测试了一下,使用wait-for-it.sh探测eureka的8761端口。发现虽然端口探测成功了,但是并不代表eureka完全启动好了。因此此时无法访问eureka的页面!
那么如何判断eureka完全启动好了呢?很简单,只需要访问eureka页面,http状态码为200,就表示启动好了。
curl -I -m 10 -o /dev/null -s -w %{http_code} http://eureka-server:8761
那么问题来了,还是得需要自己写检查脚本才行。
check_eureka.sh
#!/bin/bash
while :
do
# 访问eureka注册中心,获取http状态码
CODE=`curl -I -m 10 -o /dev/null -s -w %{http_code} http://kitedge-eureka-server:8761`
# 判断状态码为200
if [[ $CODE -eq 200 ]]; then
# 输出绿色文字,并跳出循环
echo -e " 33[42;34m kitedge-eureka-server is ok 33[0m"
break
else
# 暂停1秒
sleep 1
fi
done
# while结束时,也就是eureka启动完成后,执行容器中的run.sh。
bash /run.sh
说明:访问eureka注册中心,获取http状态码。当为200时,跳出循环,执行其他容器中的run.sh。
否则就一直循环,直到eureka页面正常为止。
目录结构
/opt/springcloud 目录结构如下:
./
├── auth
│ ├── auth-server.jar
│ ├── dockerfile
│ ├── repositories
│ └── run.sh
├── check_eureka.sh
├── docker-compose.yml
├── eureka
│ ├── dockerfile
│ ├── eureka-server.jar
│ ├── repositories
│ └── run.sh
├── gateway
│ ├── dockerfile
│ ├── gateway-server.jar
│ ├── repositories
│ └── run.sh
└── user
├── dockerfile
├── repositories
├── run.sh
└── user-service.jar
这里有4个微服务
docker-compose.yml
version: '3'
services:
eureka-server:
image: eureka-server:1
container_name: eureka-server
build: ./eureka
volumes:
- ./check_eureka.sh:/check_eureka.sh
- /data/log/tomcat:/data/log/tomcat
- /data/file:/data/file
environment:
- JVM=128m
ports:
- "8761:8761"
networks:
test_net:
aliases:
- eureka-server
restart: always
command: ["bash","/check_eureka.sh"]
healthcheck:
test: "/bin/netstat -anpt|grep 8761"
interval: 30s
timeout: 3s
retries: 1
auth-server:
image: auth-server:1
container_name: auth-server
build: ./auth
volumes:
- ./check_eureka.sh:/check_eureka.sh
- /data/log/tomcat:/data/log/tomcat
- /data/file:/data/file
environment:
- JVM=128m
ports:
- "8888:8888"
networks:
test_net:
aliases:
- auth-server
restart: always
depends_on:
- "eureka-server"
command: ["bash","/check_eureka.sh"]
healthcheck:
test: "/bin/netstat -anpt|grep 8888"
interval: 30s
timeout: 3s
retries: 1
user-service:
image: user-service:1
container_name: user-service
build: ./user
volumes:
- ./check_eureka.sh:/check_eureka.sh
- /data/log/tomcat:/data/log/tomcat
- /data/file:/data/file
environment:
- JVM=128m
ports:
- "8763:8763"
networks:
test_net:
aliases:
- user-service
restart: always
depends_on:
- "eureka-server"
command: ["bash","/check_eureka.sh"]
healthcheck:
test: "/bin/netstat -anpt|grep 8763"
interval: 30s
timeout: 3s
retries: 1
gateway-server:
image: gateway-server:1
container_name: gateway-server
build: ./gateway
volumes:
- ./check_eureka.sh:/check_eureka.sh
- /data/log/tomcat:/data/log/tomcat
- /data/file:/data/file
environment:
- JVM=128m
ports:
- "8081:8081"
networks:
test_net:
aliases:
- gateway-server
restart: always
depends_on:
- "eureka-server"
command: ["bash","/check_eureka.sh"]
healthcheck:
test: "/bin/netstat -anpt|grep 8081"
interval: 30s
timeout: 3s
retries