Waiting for docker compose

At EA we’re using Docker extensively. We’re deploying containers to production and we’re also running those containers locally for development and testing purposes. Our services are running in multiple containers and spinning up one service, usually involves spinning up multiple other containers. The most common scenario is running a service that depends on mysql and/or redis.

To orchestrate the containers that we run locally, we’re using docker compose. While docker-compose does a great job at running multiple containers and connecting them, it has a big flaw: it cannot wait for a service to be ready before starting the next one.

The problem is not impossible or, in most cases, it’s not even hard to solve but it requires a bit of infrastructure to make one service wait for another.

A frequently used solution is the wait-for-it script which checks if a TCP port is available. Another solution is to use curl or wget to poll an endpoint on the dependency container. A third solution that might not be available for every container, is to use some sort of SDK to do the check; in the case of mysql, you can use the mysql command line.

If a container runs more than one service, or it’s ready state is not a determined by a single state, then the burden of checking everything falls on the dependent. It also ties the two containers - if the dependency changes, the dependent might have to update the checks.

I wrote ruready to help me solve the readiness orchestration problem. ruready is a tool that exposes a single, stable HTTP endpoint to check the status of a dependency container.

The advantage of having a single endpoint, hosted on the dependency machine is that you only have to update the dependency container when this changes. Any dependent container will be unaffected.

To run ruready in a container you have to make it available to the container by downloading it when the container starts, by copying it at build time, or by mounting a folder with it, and then specify a command that checks the status of the container.

In my case, since I need to wait for mysql to become available, I can run: ruready -c mysql -- --host=localhost --port=3306 --user=u --password=p --execute=quit. While the program is running, the HTTP endpoint <host>:8099/ready tells me if the machine is ready. If it returns 200 (OK) then the machine is ready. If it returns anything else, the machine is not ready.

Then, from a dependent container, I can poll the /ready endpoint until the machine becomes available.

To learn more about ruready and see full, working examples, check out the Github project: https://github.com/victorhurdugaci/ruready.