docker compose 服务启动顺序控制的方法
概要
docker-compose可以方便组合多个docker容器服务,但是,当容器服务之间存在依赖关系时,docker-compose并不能保证服务的启动顺序.
docker-compose中的depends_on配置是容器的启动顺序,并不是容器中服务的启动顺序.
问题重现
首先,我们构造一个示例,来演示docker-compose带来的问题.docker-compose.yml文件如下:
version:'2' services: web: image:ubuntu:14.04 depends_on: -web command:nc-zdatabase3306 database: image:ubuntu:14.04 command:> /bin/bash-c' sleep5; echo"sleepover"; nc-lk0.0.0.03306; '
启动后,可以发现,确实是先启动database,后启动web,但是database中的服务是在大约5秒后才完成的,所以导致web的启动失败.
$docker-composeup Creatingtmp_database_1...done Creatingtmp_database_1... Creatingtmp_web_1...done Attachingtotmp_database_1,tmp_web_1 tmp_web_1exitedwithcode1 database_1|sleepover
问题解决方式1.0
修改web的启动脚本,等待database的端口通了之后再启动服务
version:'2' services: web: image:ubuntu:14.04 depends_on: -database command:> /bin/bash-c' while!nc-zdatabase3306; do echo"waitfordatabase"; sleep1; done; echo"databaseisready!"; echo"startwebservicehere"; ' database: image:ubuntu:14.04 command:> /bin/bash-c' sleep5; echo"sleepover"; nc-lk0.0.0.03306; '
再次启动,
$docker-composeup Creatingtmp_database_1...done Creatingtmp_database_1... Creatingtmp_web_1...done Attachingtotmp_database_1,tmp_web_1 web_1|waitfordatabase web_1|waitfordatabase web_1|waitfordatabase web_1|waitfordatabase web_1|waitfordatabase database_1|sleepover web_1|databaseisready! web_1|startwebservicehere tmp_web_1exitedwithcode0
web会在database启动完成,端口通了之后才启动.
问题解决方式2.0
上面的解决方式虽然能够解决问题,但是在yaml中直接插入脚本不好维护,也容易出错.如果有多个依赖,或者多层依赖的时候,复杂度会直线上升.
所以,要封装一个entrypoint.sh脚本,可以接受启动命令,以及需要等待的服务和端口.脚本内容如下:
#!/bin/bash #set-x #****************************************************************************** #@file:entrypoint.sh #@author:wangyubin #@date:2018-08-110:18:43 # #@brief:entrypointformanageservicestartorder #history:init #****************************************************************************** :${SLEEP_SECOND:=2} wait_for(){ echoWaitingfor$1tolistenon$2... while!nc-z$1$2;doechowaiting...;sleep$SLEEP_SECOND;done } declareDEPENDS declareCMD whilegetopts"d:c:"arg do case$argin d) DEPENDS=$OPTARG ;; c) CMD=$OPTARG ;; ?) echo"unkonwargument" exit1 ;; esac done forvarin${DEPENDS//,/} do host=${var%:*} port=${var#*:} wait_for$host$port done eval$CMD
这个脚本有2个参数,-d需要等待的服务和端口,-c等待的服务和端口启动之后,自己的启动命令
修改docker-compose.yml,使用entrypoint.sh脚本来控制启动顺序.
version:'2' services: web: image:ubuntu:14.04 depends_on: -database volumes: -"./entrypoint.sh:/entrypoint.sh" entrypoint:/entrypoint.sh-ddatabase:3306-c'echo"startwebservicehere"'; database: image:ubuntu:14.04 command:> /bin/bash-c' sleep5; echo"sleepover"; nc-lk0.0.0.03306; '
实际使用中,也可以将entrypoint.sh打包到发布的镜像之中,不用通过volumes配置来加载entrypoint.sh脚本.
测试结果如下:
$docker-composeup Startingtmp_database_1...done Startingtmp_web_1...done Attachingtotmp_database_1,tmp_web_1 web_1|Waitingfordatabasetolistenon3306... web_1|waiting... web_1|waiting... web_1|waiting... database_1|sleepover web_1|startwebservicehere tmp_web_1exitedwithcode0
补充
依赖多个服务和端口
使用上面的entrypoint.sh脚本,也可以依赖多个服务和端口,-d参数后面的多个服务和端口用逗号(,)隔开.
version:'2' services: web: image:ubuntu:14.04 depends_on: -mysql -postgresql volumes: -"./entrypoint.sh:/entrypoint.sh" entrypoint:/entrypoint.sh-dmysql:3306,postgresql:5432-c'echo"startwebservicehere"'; mysql: image:ubuntu:14.04 command:> /bin/bash-c' sleep4; echo"sleepover"; nc-lk0.0.0.03306; ' postgresql: image:ubuntu:14.04 command:> /bin/bash-c' sleep8; echo"sleepover"; nc-lk0.0.0.05432; '
执行的效果可以自行尝试.
尝试间隔的配置
每次尝试连接的等待时间可以通过环境变量SLEEP_SECOND来配置,默认2秒下面的配置等待时间设置为4秒,就会每隔4秒才去尝试mysql服务时候可连接.
version:'2' services: web: image:ubuntu:14.04 environment: SLEEP_SECOND:4 depends_on: -mysql volumes: -"./entrypoint.sh:/entrypoint.sh" entrypoint:/entrypoint.sh-dmysql:3306'echo"startwebservicehere"'; mysql: image:ubuntu:14.04 command:> /bin/bash-c' sleep4; echo"sleepover"; nc-lk0.0.0.03306; '
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。