Docker-compose编排微服务顺序启动
一、概述
微服务清单
服务名 | 端口 | 服务说明 | 依赖服务 | 启动优先级 |
eureka-service | 8761 | 服务注册与发现 | --- | 1 |
auth-service | 8888 | 认证服务 | eureka-service | 2 |
user-service | 8763 | 用户服务 | eureka-service | 2 |
gateway-service | 8081 | 网关服务 | eureka-service | 2 |
二、解决方案
针对这个问题,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 "\033[42;34m kitedge-eureka-server is ok \033[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: 1 networks: test_net: external: true
参数解释:
image:指定服务的镜像名称或镜像ID。如果镜像在本地不存在,Compose将会尝试拉取镜像。
container_name:容器名称,相当于docker run --name xxx,里面的--name参数。
build:指定Dockerfile所在文件夹的路径。Compose将会利用Dockerfile自动构建镜像,然后使用镜像启动服务容器。
volumes:挂载一个目录或者一个已存在的数据卷容器,相当于docker run -v xxx:xxx里面的-v参数。
environment:环境变量,相当于docker run -e xxx=xxx里面的-e参数。
ports:映射端口,相当于docker run -p xx:xx里面的-p参数。
networks:网络设置,这里表示连接test_net网桥,aliases表示设置别名。相当于docker run -it --network xx --network-alias xxx
restart:重启方式,相当于docker run --restart里面的--restart参数。
depends_on:指定依赖于哪个服务
command:覆盖容器启动后默认执行的命令,相当于docker run xxx /bin/bash里面最后一段命令。
healthcheck: 判断容器的状态是否正常
设置选项:
- test:测试命令
- --interval=DURATION (default: 30s),间隔
- --timeout=DURATION (default: 30s), 超时时间
- --start-period=DURATION (default: 0s),初始化时间
- --retries=N (default: 3),当连续失败指定次数后,容器状态会变成unhealthy
这里主要介绍eureka目录下的几个文件。
dockerfile
FROM mayan31370/openjdk-alpine-with-chinese-timezone:8-jdk ADD eureka-server.jar / ADD run.sh / RUN chmod 755 run.sh && mkdir -p /data/log/tomcat /data/file EXPOSE 8761 ENTRYPOINT [ "/run.sh"]
repositories
#https://mirrors.aliyun.com/alpine/v3.6/main/ #https://mirrors.aliyun.com/alpine/v3.6/community/ #aliyun https://mirrors.aliyun.com/alpine/v3.6/main/ https://mirrors.aliyun.com/alpine/v3.6/community/
run.sh
#!/bin/sh java -Xms${JVM} -Xmx${JVM} -XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=256m -jar /eureka-server.jar
再来看auth下的几个文件。
dockerfile
FROM mayan31370/openjdk-alpine-with-chinese-timezone:8-jdk ADD auth-server.jar / ADD repositories /etc/apk/repositories ADD run.sh / RUN chmod 755 run.sh && mkdir -p /data/log/tomcat /data/file && apk update && apk add bash curl EXPOSE 8888 #ENTRYPOINT [ "/run.sh"]
注意:这里注释掉了ENTRYPOINT ,因为它由check_eureka.sh脚本来启动。注意看此脚本的最后一行,它就是来执行run.sh的。
repositories
内容同上,这里就不重复贴了
run.sh
#!/bin/sh java -Xms${JVM} -Xmx${JVM} -XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=256m -jar /auth-server.jar
另外2个微服务,user和gateway。和auth也是类似的,只不过dockerfile和run.sh里面的jar包名不一样,其他内容都是一样的。
启动服务
创建bridge网络
docker network create test_net
一切准备就绪了,先build,再启动。
cd /opt/springcloud docker-compose build docker-compose up -d
等待几分钟,查看容器状态
# docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------- auth-server bash /check_eureka.sh Up (healthy) 0.0.0.0:8888->8888/tcp eureka-server /run.sh bash /check_eureka.sh Up (healthy) 0.0.0.0:8761->8761/tcp gateway-server bash /check_eureka.sh Up (healthy) 0.0.0.0:8081->8081/tcp user-service bash /check_eureka.sh Up (healthy) 0.0.0.0:8763->8763/tcp
本文参考连接: