在docker-compose编排多个容器时,需要按实际情况控制各容器的启动顺序,本文是《docker-compose下的java应用启动顺序两部曲》的第一篇,文中会分析启动顺序的重要性,以及启动顺序有问题时会有什么样的影响,再给出临时解决的和官方推荐的两种解决方案,为下一篇的实战做好铺垫。

环境信息

本次实战的环境如下:

  1. 操作系统:CentOS Linux release 7.7.1908
  2. docker:1.13.1
  3. docker-compose:1.24.1
  4. spring cloud:Finchley.RELEASE

分布式环境中的依赖关系

在分布式环境中,各服务之间可能存在依赖关系,例如SpringCloud环境中的应用在启动时都会先往注册中心Eurka发起请求,如下图(来自spring官方博客:https://spring.io/blog/2015/07/14/microservices-with-spring ):



从上图可知,如果Eureka的服务不可用,就会影响业务服务的功能;

Docker环境中的依赖关系

  1. 上述服务如果用docker-compose编排在一起,也面依赖着问题:Eureka容器启动完毕并且能提供http服务以后,业务服务的容器才能在Eureka注册成功并取得服务列表,通常我们都使用depends_on参数来设定依赖关系;
  2. 以下是个docker-compose.yml文件,里面有两个容器:eureka和service,eureka是注册中心,service是业务服务,service启动后要去eureka注册,为了确保启动顺序,service配置了depends_on参数:
version: '3'
services:
eureka:
image: bolingcavalry/eureka:0.0.1-SNAPSHOT
container_name: eureka
restart: unless-stopped
service:
image: bolingcavalry/service:0.0.1-SNAPSHOT
container_name: service
restart: unless-stopped
command: sh -c 'java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication'
depends_on:
- eureka
  1. 上述yml文件能解决依赖问题吗?service服务启动时能否成功在eureka注册?来试试吧,在Linux电脑上创建docker-compose.yml文件,内容如上所示;
  2. 在docker-compose.yml所在目录执行docker-compose up,docker服务会先去hub.docker.com下载镜像,然后依次创建容器,控制台会同时打印eureka和service的日志,如下图所示,service注册eureka失败了,请注意图中的文字分析:

  3. 为何会注册失败呢?继续看后面的日志,如下图,service注册失败后eureka才初始化完成,所以前面的service注册会失败:

  4. 至此可以确定:depends_on参数可以确保eureka容器启动后再启动service容器,但我们真正想要的,是eureka容器启动后,并且eureka服务初始化完毕进入可用状态后,再启动service容器,显然depends_on参数达不到我们的要求;
  5. docker官方文档也证实了这一点,如下图红框所示:

  6. 看来depends_on参数解决不了我们的问题,需要去寻找其他方法;

另外您可能会说:没关系,service会自动重新注册,但是在真实环境中,不是每个服务都有能力去自己解决依赖不可用的问题,例如spring-cloud-config服务如果起不来,依赖它的服务可能会立即停止;

有一种临时方法(此方法V3版语法不再支持)

  1. 如果eureka容器配置了健康检查,那么service容器可以配置健康检查依赖来控制启动时机,具体的做法可以参考官方示例,如下所示,地址是:https://docs.docker.com/compose/compose-file/compose-file-v2/
version: "2.4"
services:
web:
build: .
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
redis:
image: redis
db:
image: redis
healthcheck:
test: "exit 0"

从上述编排内容可见:db容器有健康检查,可以确定db容器的服务是否可用,web容器的depends_on参数内可以配置condition,这样就做到了只有redis已经启动并且db的健康检查通过,才会启动web容器;

2. 上述配置看起来似乎是个不错的方案,在我们这里,只要给eureka配置要健康检查,再让service容器的depends_on参数内配置condition: service_healthy就可以了;

3. 不幸的是:在docker-compose的第三版语法中,取消了condition参数!文档地址是:https://docs.docker.com/compose/compose-file/ ,如下图红框所示:



4. 因此,condition参数看似好用,但是从V3版开始的docker-compose.yml已经不再支持该参数,不能作为标准的解决方案;

官方推荐的方案

如下图红框所示,docker官方推荐使用wait-for-it.sh脚本来解决问题,地址:https://docs.docker.com/compose/startup-order/



至此,本篇已经分析了docker-compose下容器启动顺序的问题,下一篇文章,我们用SpringCloud应用来做实战,将其做到在docker-compose下有序启动;

参考文章

如果您对docker容器健康检查有兴趣,可以参考以下文章:

  1. 《极速体验docker容器健康》
  2. 《Java应用在docker环境配置容器健康检查》

欢迎关注公众号:程序员欣宸

docker-compose下的java应用启动顺序两部曲之一:问题分析的更多相关文章

  1. docker-compose下的java应用启动顺序两部曲之二:实战

    上篇回顾 本文是<docker-compose下的java应用启动顺序两部曲>的终篇,在上一篇<docker-compose下的java应用启动顺序两部曲之一:问题分析>中,我 ...

  2. 第一课:Centos下配置java环境变量的两种方式(jdk1.8)

    配置java环境(yum安装) 1.查出java1.8的全部版本 yum list java-1.8* 2.安装你需要的java1.8 版本(安装的名字根据查询出来的结果输入这里只是举例) yum i ...

  3. Docker创建MySQL容器环境两部曲

    1:下载MySQL镜像 需要执行以下命令,确保主机或者VM联网,从官网下载mysql的最新镜像(镜像版本以官网为主) docker  pull  mysql 下载成功后执行 docker image ...

  4. Docker学习笔记之常用的 Docker Compose 配置项

    0x00 概述 与 Dockerfile 一样,编写 Docker Compose 的配置文件是掌握和使用好 Docker Compose 的前提.编写 Docker Compose 配置文件,其本质 ...

  5. Docker小白到实战之Docker Compose在手,一键足矣

    前言 Docker可以将应用程序及环境很方便的以容器的形式启动,但当应用程序依赖的服务比较多,或是遇到一个大系统拆分的服务很多时,如果还一个一个的根据镜像启动容器,那就有点累人了,到这有很多小伙伴会说 ...

  6. docker和docker compose安装使用、入门进阶案例

    一.前言 现在可谓是容器化的时代,云原生的袭来,导致go的崛起,作为一名java开发,现在慌得一批.作为知识储备,小编也是一直学关于docker的东西,还有一些持续继承jenkins. 提到docke ...

  7. Docker学习笔记之使用 Docker Compose 管理容器

    0x00 概述 通过之前的介绍,我们已经基本掌握了构建.运行容器的方法,但这还远远不够,由于 Docker 采用轻量级容器的设计,每个容器一般只运行一个软件,而目前绝大多数应用系统都绝不是一个软件所能 ...

  8. Docker Compose的安装及命令补全

    安装Compose Compose的安装有多种方式,例如通过shell安装.通过pip安装.以及将compose作为容器安装等等.本文讲解通过shell安装的方式.其他安装方式如有兴趣,可以查看Doc ...

  9. 控制Docker Compose的启动顺序的一个思路

    起源 守护进程daemon 从守护进程的角度看Docker Compose Docker的解决方案 思路 代码 结果 起源 Docker Compose提供了一个depends_on参数. https ...

随机推荐

  1. springboot新版本(2.0.0+)自定义ErrorController中使用ErrorAttributes

    2.0.0之前使用: @Autowired private ErrorAttributes errorAttributes; private Map<String, Object> get ...

  2. 正睿OI国庆DAY2:图论专题

    正睿OI国庆DAY2:图论专题 dfs/例题 判断无向图之间是否存在至少三条点不相交的简单路径 一个想法是最大流(后来说可以做,但是是多项式时间做法 旁边GavinZheng神仙在谈最小生成树 陈主力 ...

  3. 如何编写高质量的 JS 函数(3) --函数式编程[理论篇]

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/EWSqZuujHIRyx8Eb2SSidQ作者:杨昆 [编写高质量函数系列]中, <如何 ...

  4. JS调用activeX实现浏览本地文件夹功能 wekit内核只需要<input type="file" id="files" name="files[]" webkitdirectory/>即可,IE内核比较麻烦

    研究了一天,js访问本地文件本身是不可能的,只能借助于插件.植入正题,IE仅支持ActiveX插件. function openDialog() { try { var Message = " ...

  5. vertical-align之见

    ertical-align   英文翻译为垂直对齐 ,常用来应用于table 表格中文字的垂直居中:脱离表格后不常用: 有朋友问起:故总结记之: 开局一张图,下来全靠编 这是一个简单的四线表格,小学时 ...

  6. MongoDB 学习笔记之 $push,$each,$slice组合使用

    $push使用: 使用$push给数组添加2个新成员 db.ArrayTest.updateOne({ "name" : "Bill"},{$push: {&q ...

  7. A-05 前向选择法和前向梯度法

    目录 前向选择法和前向梯度法 一.前向选择法 1.1 余弦相似度求投影 1.2 举例 1.3 前向选择法优缺点 1.3.1 优点 1.3.2 缺点 二.前向梯度法 2.1 举例 2.2 前向梯度法优缺 ...

  8. 网络请求中的cookie与set-Cookie的交互模式的一些问题解析

    首先我们需要思考,很多问题. 1.当很多人访问统一个网服务器,服务器如何来区分不同的用户呢? 答:sessionid,sessionid保证了浏览器和服务器唯一性的通信凭证号码,session保存在服 ...

  9. LRU算法实现,HashMap与LinkedHashMap源码的部分总结

    关于HashMap与LinkedHashMap源码的一些总结 JDK1.8之后的HashMap底层结构中,在数组(Node<K,V> table)长度大于64的时候且链表(依然是Node) ...

  10. .net core gRPC与IdentityServer4集成认证授权

    前言 随着.net core3.0的正式发布,gRPC服务被集成到了VS2019.本文主要演示如何对gRPC的服务进行认证授权. 分析 目前.net core使用最广的认证授权组件是基于OAuth2. ...