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
sqlservr
is up and running; - Create a new database with the name
phonebookdatabase
; - Inside the
phonebookdatabase
create tablePhoneBook
with two fields PersonName, PhoneNumber;
Steps inside the phone-book-writer
service container:
- Wait for
mssql
service is ready; - Insert new records into the
PhoneBook
table;
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:
-
sqlservr
is up and running; -
phonebookdatabase
is created; -
PhoneBook
is created; -
readiness.py
is 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_on
only indicates that the container is running.healthcheck
was 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:1444
wait for port 1444 to be avaialable; - Access
mssql
1433 and executes sql statements from_main.sql
script;
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.