2018-11 from--https://www.jianshu.com/p/2f8da2a45d6d
废话:
一个稍微复杂点的项目,肯定不是一个单独的程序可以解决的,必定是许多程序组合起来的一个整体,它们之间存在一定的依赖关系,比如:nginx依赖web应用服务器tomcat,tomcat中的应用依赖mysql数据库和zookeeper配置,tomcat中的应用可能互相依赖等。本篇文章为了解决多个程序/服务部署在docker容器中如何根据依赖关系按顺序启动的问题。
普通的部署方式(直接在服务器安装各个应用:tomcat、mysql、nginx、zookeeper等)
如果人工去启动多个应用,肯定是等被依赖的服务准备好之后,再去启动下一个应用/服务;但是想要服务器自动启动就要靠脚本来检测被依赖的服务是否准备好,然后按顺序启动之后的应用/服务。
docker 容器部署方式(将各个应用部署到单独的容器中)
docker容器通过服务编排(docker-compose)的方式启动时,可以通过==depends_on==来配置被依赖容器,待被依赖的容器启动之后,才启动当前的容器,但隐含的问题是:容器启动之后,容器中的应用不一定可以准备好,就比如电脑启动之后,自启动应用不一定启动了,这中间会有时间间隔。为解决这个问题,我们必需判断具体的应用是否启动好了。
1. 第一种解决办法(比较low),通过写wait-for-it.sh脚本
因为项目里面多个tomcat应用存在依赖关系,应用的启动顺序无法保证,所以写了一个wait-for-it.sh 脚本,通过curl tomcat的页面来判断tomcat就否启动好。
注:tomcat启动时,当所有应用启动完成后才会将开启HTTP端口
#!/bin/bash
# wait-for-it.sh
set -e
host="$1"
shift
cmd="$@"
curl -I "${host}" > a.txt
status = cat a.txt|head -1|awk '{print $2}'
until $status="200"; do
>&2 echo "${host} is unavailable - sleeping"
sleep 1
done
>&2 echo "${host} is up - executing command"
exec $cmd
在docker-compose.yaml各个服务的command中的配置如下:
command: ["/wait-it-for.sh", "host:8080", "/usr/bin/supervisord"]
该脚本的缺点:
- 只支持http的方式来判断;
- 只支持依赖一个服务
2. 通过dockerize 工具来判断
dockerize可以做以下几件事:
1. 可以用来在容器启动时以模板和环境变量生成配置文件;
2. 将任意的日志文件转到标准输出和标准错误中;
3. 等待TCP、HTTP(S)服务可用之后启动主进程
dockerize文档 、
dockerize GIT地址
在解决服务依赖问题上使用dockerize:
在docker-compose.yaml各个服务的command中的配置如下:
command: ["dockerize", "-wait", "tcp://zookeeper:2181", "-wait", "tcp://mysql:3306", "-wait", "http://apphost:8080", "-timeout", "1800s", "/usr/bin/supervisord"]
选项说明:
-wait <protocol://host:port>
-wait 参数可以添加多个,代表依赖多个服务
-timeout 1800s
-timeout 后面跟持续等待的秒数,默认是10秒
最后一个命令是各依赖服务准备好之后要执行的命令,也就是当前应用启动的命令
支持的协议有:file, tcp, tcp4, tcp6, http, https and unix