Control docker-compose startup flow with readiness probe
Contents
Docker-compose is a powerful tool to run an isolated environment for the application.
However, it doesn’t provide one important feature right out of the box which is startup control.
- What if the containerized application requires a database to be up and ready and fully provisioned?
- How to check if a certain process is finished in another container?
If you encounter such issues lets dive into the solution.
Database and Service in docker-compose
Assume we have a simple service phone-book-writer, which populates the PhoneBook table with some records. When this service runs it expects that phonebookdatabase and PhoneBook already exist.
Steps inside the mssql database container:
- Wait while the
sqlservris up and running; - Create a new database with the name
phonebookdatabase; - Inside the
phonebookdatabasecreate tablePhoneBookwith two fields PersonName, PhoneNumber;
Steps inside the phone-book-writer service container:
- Wait for
mssqlservice is ready; - Insert new records into the
PhoneBooktable;
Descliamer
It’s possible to create a new database and table inside thephone-book-writer container instead but this is not what we want to achieve. imagine instead of phone-book-writer could be a .net core application or another service, which expects the database is already provisioned.Database container
mssql container instance is based on mcr.microsoft.com/mssql/server:2019-latest docker image.
| |
Container startup script is overriten with mssql/scripts/entrypoint.sh:
| |
The & in bash ./configure-db.sh & allows to execute script in background.
It means that floowing command /opt/mssql/bin/sqlservr won’t wait for configure-db.sh to complete.
The configure-db.sh has following responsibilities:
-
sqlservris up and running; -
phonebookdatabaseis created; -
PhoneBookis created; -
readiness.pyis started;
Startup control
readiness.py script plays the glue role between the mssql and phone-book-writer.
This is a simple service which listens for specified port 1444 and responds with HTTP 200 / OK.
In other words when the port 1444 is available the mssql database is up and fully provisioned.Not working approaches
Docker-compose provides two features depends_on and healthcheck.
But they are not guaranteed that service is ready.
depends_ononly indicates that the container is running.healthcheckwas useful in docker-compose version 2.x but doesn’t provide expected behavior for version 3.x.
Service container
phone-book-writer service container instance is based on mcr.microsoft.com/mssql-tools docker image.
However it misses some important tools to lister if port 1444 is available. Let’s add them into the PhoneBookWriter/Dockerfile:
| |
| |
Container startup script PhoneBookWriter/scripts/entrypoint.sh implements following flow:
-
wait-for-it.sh mssql:1444wait for port 1444 to be avaialable; - Access
mssql1433 and executes sql statements from_main.sqlscript;
Startup control
wait-for-it.sh listens for port 1444 in the container which is served by readiness.py script inside the mssql container.Results
The complete solution can be found in the following repository: blog-docker-compose-control-startup
To try you need to clone the repository to your local computer:
| |
To start docker-compose and force build dockerfile:
| |
After phone-book-writer completed the PhoneBook table contain 2 records.
The phonebookdatabase can be accesable via localhost with port 1433 and password 1234567_A.
To stop in interactive mode press Ctrl+C in either case use the docker-compose command:
| |
With the help of this approach it’s possible to create self-contained integration tests or run applications with required infrastructure such as database, event, etc.
