We have a bash script that installs a program, which includes running a docker-compose file. One of the services, RabbitMQ, takes some time to load and I need a command to wait until it's loaded before the other services are loaded. We were using a sleep command, but our customers use different laptops, so it takes longer to load on some than others. Is there a way to just hold it until it finishes loading the service before moving on to the next without using the sleep command? I have included the part of the script below. Thanks!
# 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 &
As already stated in the other answers you'll have to do an application-specific readiness-check for your container. Personally I prefer to provide these checks/scripts with the container image, e.g. by adding the wait-for-it.sh (see ErikMD's answer) or similar scripts to the image and executing them within the running container e.g. with docker exec (as proposed by Ahmed Arafa's answer).
This has some advantages over running the check on the host:
wget/curl available on the host, or even a bash/shell? Is the docker/docker-compose command executed on the same host as the docker deamon, i.e. could you reach the container via localhost?)So, to apply this method to your example, simply add a script - e.g. is_ready.sh - to the image, execute it within the container with docker-compose exec and act upon its exit status:
# Execute applications
cd /opt/program
docker-compose up -d
echo "waiting for message queue..."
while ! docker-compose exec rabbitmq /is_ready.sh; do sleep 1; done
echo "starting ingest manager"
cd /opt/program/scripts
chmod +x start-manager.sh
./start-manager.sh &
where is_ready.sh may look like this:
#!/bin/bash
rabbitmqctl status
Going even further down this road you may leverage the native healtcheck feature of docker and docker-compose. With these docker will automatically execute the defined healthcheck script/command and indicate the current health in the container status.
Incorporated into your script this could look like:
# 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 &
with the healthcheck defined in the docker-compose.yml
...
services:
rabbitmq:
...
healtcheck:
test: rabbitmqctl status
For more complex healthchecks you can also add a longer script to the image and execute that instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With