一、概述

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 "\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
访问eureka注册中心
 
效果如下:

 
 

本文参考连接:

https://blog.csdn.net/wuzhong8809/article/details/82500722

https://www.jianshu.com/p/d2f39703bcb5

Docker-compose编排微服务顺序启动的更多相关文章

  1. 使用Docker Compose编排微服务

    一般微服务架构会包含若干个微服务,而每个微服务可以有多个实例,如果每个微服务都有手动启停,那么效率就很低.维护量比较大. 所以我们可以使用Docker Compose来轻松.高效地管理容器. 一.安装 ...

  2. 使用Docker Compose编排Spring Cloud微服务

    文章目录 微服务构建实例 简化Compose的编写 编排高可用的Eureka Server 编排高可用Spring Cloud微服务集群及动态伸缩 微服务项目名称 项目微服务中的角色 microser ...

  3. 使用Docker compose编排Laravel应用

    前言 Laravel官方开发环境推荐的是Homestead(其实就是一个封装好的Vagrant box),我感觉这个比较重,于是自己用Docker compose编排了一套开发环境,在这里分享下. 环 ...

  4. Docker从入门到掉坑(二):基于Docker构建SpringBoot微服务

    本篇为Docker从入门到掉坑第二篇:基于Docker构建SpringBoot微服务,没有看过上一篇的最好读过 Docker 从入门到掉坑 之后,阅读本篇. 在之前的文章里面介绍了如何基于docker ...

  5. Docker Compose编排工具部署lnmp实践及理论(详细)

    目录 一.理论概述 编排 部署 Compose原理 二.使用docker compose 部署lnmp 三.测试 四.总结 一.理论概述 Docker Compose是一个定义及运行多个Docker容 ...

  6. SpringCloud微服务实战——搭建企业级开发框架(三十五):SpringCloud + Docker + k8s实现微服务集群打包部署-集群环境部署

    一.集群环境规划配置 生产环境不要使用一主多从,要使用多主多从.这里使用三台主机进行测试一台Master(172.16.20.111),两台Node(172.16.20.112和172.16.20.1 ...

  7. Docker(二十六)-Docker Compose编排容器

    1. 前言 Docker Compose 是 Docker 容器进行编排的工具,定义和运行多容器的应用,可以一条命令启动多个容器. 使用Compose 基本上分为三步: Dockerfile 定义应用 ...

  8. Docker系列之(五):使用Docker Compose编排容器

    1. 前言 Docker Compose 是 Docker 容器进行编排的工具,定义和运行多容器的应用,可以一条命令启动多个容器. 使用Compose 基本上分为三步: Dockerfile 定义应用 ...

  9. 基于docker部署的微服务架构(四): 配置中心

    原文:http://www.jianshu.com/p/b17d65934b58%20 前言 在微服务架构中,由于服务数量众多,如果使用传统的配置文件管理方式,配置文件分散在各个项目中,不易于集中管理 ...

随机推荐

  1. IDLE怎么修改背景?

    摘要:IDLE默认为白色,可能有的人喜欢其他颜色,那么怎么修改呢? 颜色喜好,因人而异.不想千篇一律使用默认的白色,可以通过以下操作修改IDLE的背景颜色以及其他设置. 打开Python官方自带的ID ...

  2. P3195 [HNOI2008] 玩具装箱(斜率优化DP)

    题目链接 设\(d[i]\)为将前 \(i\) 个玩具装入箱中所需得最小费用 容易得到动态转移方程: \[d[i] = min(d[j] + (s[i]-s[j]+i-j-1-L)^2), (j< ...

  3. Codeforces Round #613 (Div. 2) C. Fadi and LCM(LCM & GCD)

    题意: LCM(a, b) = X,求 max(a, b) 的最小值. 思路: a, b 只可能存在于 X 的因子中,枚举即可. #include <bits/stdc++.h> usin ...

  4. codeforces B. Pasha and String

    Pasha got a very beautiful string s for his birthday, the string consists of lowercase Latin letters ...

  5. 【noi 2.6_9268】酒鬼(DP)

    题意:有N瓶酒,不能连续喝>=3瓶的酒,问能喝的最大的酒量. 解法:同前一题相似,可以f[i][j]表示前i瓶中连续喝了j瓶的最大酒量.1.f[i][0]=f[i-1][3] ; 2.i=1或2 ...

  6. Educational Codeforces Round 94 (Rated for Div. 2) B. RPG Protagonist (数学)

    题意:你和你的随从去偷剑和战斧,你可以最多可以拿\(p\)重的东西,随从可以拿\(f\)重的东西,总共有\(cnt_{s}\)把剑,\(cnt_{w}\)把战斧,每把剑重\(s\),战斧重\(w\), ...

  7. LianLianKan HDU - 4272 状压dp

    题意:长度为n(n<=1000)的栈,栈顶元素可以与下面1~5个数中相同的元素消去,问最后能都完全消去. 题解: 比如这个序列12345678910112这个位置的最远可匹配位置能到11为什么呢 ...

  8. IIS Web API 长时间不连接后第一次访问非常缓慢

    搭建在 IIS 上的 Web API 若长时间不访问,会出现第一次访问耗时较长的现象,这与其调用应用程序池的 Idle Time-out(minutes) 即闲置超时设置有关.默认值为20,修改为0即 ...

  9. 谈到云原生, 绕不开"容器化"

    传送门 什么是云原生? 云原生设计理念 .NET微服务 Containers 现在谈到云原生, 绕不开"容器". 在<Cloud Native Patterns>一书中 ...

  10. Linux-压缩/解压缩命令

    目录 Linux系统中常见的压缩包格式 gzip 压缩命令 zip 压缩命令 tar 压缩命令(归档) Linux系统中常见的压缩包格式 格式 压缩工具 .zip zip压缩工具 .gz gzip压缩 ...