I am deploying a few different docker containers, mysql being the first one. I want to run scripts as soon as database is up and proceed to building other containers. The sc
I developed a new solution for this issue based on a new approach. All approaches I found rely on a script that tries over and over to connect to the database, or try to establish a TCP connection with the container. The full details can be found on the waitdb repository, but, my solution is to rely on the retrieved log from the container. The script waits until the log fires the message ready for connections. The script can identify if the container is starting for the first time. In this case the script waits until the initial database script is executed and the database is restarted, waiting again for a new ready for connections message. I tested this solution on MySQL 5.7 and MySQL 8.0.
The script itself (wait_db.sh):
#!/bin/bash
STRING_CONNECT="mysqld: ready for connections"
findString() {
($1 logs -f $4 $5 $6 $7 $8 $9 2>&1 | grep -m $3 "$2" &) | grep -m $3 "$2" > /dev/null
}
echo "Waiting startup..."
findString $1 "$STRING_CONNECT" 1 $2 $3 $4 $5 $6 $7
$1 logs $2 $3 $4 $5 2>&1 | grep -q "Initializing database"
if [ $? -eq 0 ] ; then
echo "Almost there..."
findString $1 "$STRING_CONNECT" 2 $2 $3 $4 $5 $6 $7
fi
echo "Server is up!"
The script can be used in Docker Compose or in Docker itself. I hope the examples bellow make the the usage clear:
SERVICE_NAME="mysql" && \
docker-compose up -d $SERVICE_NAME && \
./wait_db.sh docker-compose --no-color $SERVICE_NAME
CONTAINER_NAME="wait-db-test" && \
ISO_NOW=$(date -uIs) && \
docker run --rm --name $CONTAINER_NAME \
-e MYSQL_ROOT_PASSWORD=$ROOT_PASSWORD \
-d mysql:5.7 && \
./wait_db.sh docker --since "$ISO_NOW" $CONTAINER_NAME
A full example can be found on the test case of the repository. This test-case will startup a new MySQL, create a dummy database, wait until everything is started and then fires a select to check if everything goes fine. After that it'll going restart the container and wait it to be started and then fires a new select to check if it's ready for connection.