Bash脚本命令等待docker-compose过程完成后再继续

时间:2019-08-15 18:53:37

标签: linux bash docker docker-compose

我们有一个bash脚本,用于安装程序,其中包括运行docker-compose文件。其中一项服务RabbitMQ需要花费一些时间来加载,因此我需要一个命令来等待其加载,然后再加载其他服务。我们使用的是sleep命令,但是我们的客户使用不同的笔记本电脑,因此在某些笔记本电脑上的加载时间比其他笔记本电脑更长。有没有办法在不使用sleep命令的情况下,一直保持它直到完成服务加载,然后再转到下一个?我在下面包括了脚本的一部分。谢谢!

# Execute applications
cd /opt/program
docker-compose up -d
echo "waiting for message queue..."
sleep 15

echo "starting ingest manager"

cd /opt/program/scripts
chmod +x start-manager.sh
./start-manager.sh &

3 个答案:

答案 0 :(得分:1)

docker-compose up -d命令在“分离模式”下在后台运行,但是我想您的设置至少公开了一个Web服务… 如果是,则可以依靠wait-for-it之类的工具来精确地等待此服务准备就绪。

首先,下载并检查此脚本:

https://github.com/vishnubob/wait-for-it/raw/master/wait-for-it.sh

接下来,假设您的docker-compose.yml设置通过以下内容公开了localhost:9090处的Web服务:

version: 3
services:
  frontend:
    image: user/image
    ports:
      - '9090:8080'

您可以按以下方式重构您的Bash脚本(命名为run.sh):

#!/bin/bash

# retrieve and remember the directory where is stored this script
srcdir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )
# we assume the script "wait-for-it.sh" is also in this directory

# Execute applications
cd /opt/program
docker-compose up -d

# Change the working directory now
cd /opt/program/scripts
chmod +x start-manager.sh

echo "waiting for message queue..."
"$srcdir/wait-for-it.sh" -h localhost -p 9090 -s -t 0 -- ./start-manager.sh

有关更多详细信息,请参见一些在线文档。可在https://github.com/vishnubob/wait-for-it#readme

获得

答案 1 :(得分:1)

正如其他答案中已经提到的那样,您将必须对容器进行特定于应用程序的准备情况检查。就我个人而言,我更喜欢为这些支票/脚本提供容器图片,例如通过向图像添加wait-for-it.sh(请参见ErikMD's answer)或类似脚本,然后在运行容器中执行它们,例如与docker exec(由Ahmed Arafa's answer提议)。

与在主机上运行检查相比,它具有一些优点:

  • 您可以在容器映像中提供所有必需的脚本和依赖项
  • 您不需要对主机进行任何假设(例如,通过api端点进行测试时:主机上是否有wget / curl甚至是bash / docker / docker-compose命令是否与docker deamon在同一主机上执行,即您可以通过localhost到达容器吗?)
  • 您不必将任何端口/端点暴露给外界仅用于检查容器状态
  • 您可以为图像的不同版本提供不同的检查脚本,而无需修改启动脚本

因此,要将这种方法应用于您的示例,只需添加一个脚本-例如is_ready.sh-对于图像,使用docker-compose exec在容器中执行它,并根据其退出状态采取行动:

# Execute applications
cd /opt/program
docker-compose up -d
echo "waiting for message queue..."

while ! docker-compose exec rabbitmq /is_ready.sh; sleep 1; done

echo "starting ingest manager"

cd /opt/program/scripts
chmod +x start-manager.sh
./start-manager.sh &

其中is_ready.sh可能看起来像这样:

#!/bin/bash

rabbitmqctl status

再往前走,您可以利用dockerdocker-compose的本机healtcheck功能。借助这些docker,将自动执行定义的运行状况检查脚本/命令,并在容器状态中指示当前运行状况。

合并到您的脚本中后,可能看起来像这样:

# Execute applications
cd /opt/program
docker-compose up -d
echo "waiting for message queue..."

is_healthy() {
    service="$1"
    container_id="$(docker-compose ps -q "$service")"
    health_status="$(docker inspect -f "{{.State.Health.Status}}" "$container_id")"

    if [ "$health_status" = "healthy" ]; then
        return 0
    else
        return 1
    fi
}

while ! is_healthy rabbitmq; do sleep 1; done

echo "starting ingest manager"

cd /opt/program/scripts
chmod +x start-manager.sh
./start-manager.sh &

具有docker-compose.yml

中定义的运行状况检查
...
services:
  rabbitmq:
    ...
    healtcheck:
      test: rabbitmqctl status      

对于更复杂的运行状况检查,您还可以在图像中添加更长的脚本,然后执行该脚本。

答案 2 :(得分:0)

首先,您需要通过添加以下内容来确定docker-compose.yaml中Rabbitmq容器的特定名称:

version: "3"

services:
        web:
                image: rabbitmq:latest
                container_name: rabbitmq

服务障碍

脚本如下:

#!/bin/bash
cd /opt/program
docker-compose up -d
echo "waiting for message queue..."

rabbitmq_status() { 
        docker exec -it rabbitmq rabbitmqctl status
}

rabbitmq_status

if [ $? -eq 0 ]
then
        echo "starting ingest manager"
        cd /opt/program/scripts
        chmod +x start-manager.sh
        ./start-manager.sh &
else
        echo "rabbitmq container is not running"
fi

在rabbitmq容器启动并运行之前,不会进行下一步。