docker-compose 容器编排启动时程序启动顺序的控制解决

in 工作记录 with 0 comment

docker-compose 编排多个容器启动的时候,depends_on 只能影响容器的启动顺序,如果一个容器的程序必须依赖另外一个,就有可能出现依赖的程序还未启动而导致的问题...

问题描述

我遇到此问题是因为有一个.net的项目要一同部署到我们的集群中,此项目需要连接到我们eureka注册中心,但是它启动时只会连接一次注册中心,如果没有连接上就会报错停止工作,但是我无法修改此程序的代码。

所以就要想其他的办法解决。

首先docker中的程序启动必然会配置容器启动时执行的命令,这样才能启动容器中的程序,所以首先查看容器启动时候执行的内容。

inspect 可以查看容器的细节,找到 "Entrypoint" 这个属性。

docker inspect imageName

效果:
image.png

发现 Entryponint 只有一句

dotnet ***.dll --server.urls ...

大概是通过.dll动态库文件直接启动的。

要让命令在eureka工作后再启动,肯定要用shell脚本来解决了,查了下各种方案,比较靠谱的就是,利用nc命令判定eureka端口启动成功后再执行,nc 就是 netcat的缩写。

为了方便扩展,我创建了启动用的 start.sh脚本。

测试脚本

写了个非常简单的测试脚本

  1. 首先定义了waitPort方法
  2. 然后执行了waitPort方法 参数$1为地址,参数$2为端口
  3. waitPort方法中会检测 nc -vz $1 $2 的结果
  4. nc -vz $1 $2 的结果 为 不通则2秒后再试
  5. nc -vz可以检测这个地址的端口有没有通
  6. 通了就会往下走 echo 打印 ok!
#!/bin/bash

function waitPort() {
    while ! nc -vz $1 $2; do
        sleep 2
    done
}

 waitPort www.baidu.com 80

 echo 'ok!'

设置sh的执行权限

chmod 744 start.sh
image.png

执行测试

 ./start.sh

image.png
放个错误域名测试不通的情况

#!/bin/bash

function waitPort() {
    while ! nc -vz $1 $2; do
        sleep 2
    done
}

 waitPort www.baidu.com22  80

 echo 'ok!'

两秒重复一次, 工作正常.
image.png

改造start.sh和DockerFile

完全体start.sh
image.png

启动脚本做好了, 首先查看了此镜像的DockerFile , ENTRYPOINT 从原来的 dotnet ***.dll 替换为

 ENTRYPOINT ["./start.sh"]

镜像的工作目录中放入了start.sh (记得设好执行权限)

执行测试了下,发现容器没有nc命令,所以还要再DockerFile中安装下
这边使用apt-get安装的 DockerFile 中 加上 RUN 配置。

RUN apt-get update
&& DEBIAN_FRONTEND=noninteractive apt-get install -y
netcat

完全体DockerFile

image.png

启动测试成功 后面就不展示啦~