DMCApps
DMCApps

Reputation: 2168

Makefile docker wait for database to be ready

I'm attempting to create a makefile that will launch my db container, wait for it to complete before launching the rest of my app.

I have 2 compose files.

My make file is as follows:

default:
    @echo "Preparing database"
    docker-compose -f docker-compose.db.yml build
    docker-compose -f docker-compose.db.yml pull
    docker-compose -f docker-compose.db.yml up -d

    @echo ""
    @echo "Waiting for database \"ready for connections\""
    @while [ -z "$(shell docker logs $(PROJECT_NAME)_mariadb 2>&1 | grep -o "ready for connections")" ]; \
    do \
        sleep 5; \
    done 
    @echo "Database Ready for connections!"

    @echo ""
    @echo "Launching App Containers"
    docker-compose build
    docker-compose pull
    docker-compose up -d

What happens is that it immediately goes to "Database Ready for connections!" even before the database is ready. If I run the same command in terminal it response with empty for about the first 20 seconds and then finally returns "ready for connections".

Thank you in advance

Upvotes: 5

Views: 1980

Answers (1)

David Maze
David Maze

Reputation: 159732

The GNU make $(shell ...) function gets run once when the Makefile is processed. So when your rule has

@while [ -z "$(shell docker logs $(PROJECT_NAME)_mariadb 2>&1 | grep -o "ready for connections")" ]

Make first runs the docker logs command on its own, then substitutes the result in the shell command it runs

while [ -z "ready for connections" ]

which is trivially false, and the loop exits immediately.

Instead you probably want to escape the $ in the shell substitution command

@while [ -z "$$(docker-compose logs mariadb ...) "]

It's fairly typical to configure containers to be able to wait for the database startup themselves, and to run the application and database from the same docker-compose.yml file. Docker Compose wait for container X before starting Y describes this setup.

Upvotes: 6

Related Questions