With projects that use multiple application dependencies such as WordPress or Laravel (requiring both PHP and MySQL) it can be difficult to predict when the full application stack is completely configured and ready to process requests after startup. This is especially relevant during unit testing and development, when these services run inside Docker containers.
Although Docker has a concept of container healthchecks (also in Docker Compose), they are not really usable during the local development or automated testing. The Docker documentation suggests knowing the state of the application services should be an application-level problem:
The problem of waiting for a database (for example) to be ready is really just a subset of a much larger problem of distributed systems. In production, your database could become unavailable or move hosts at any time. Your application needs to be resilient to these types of failures.— Docker documentation.
Solving the Issue
The solution is to add a bit of application logic to our codebase or the unit test bootstrap logic to wait for all the necessary services before running the tests. Existing tools like wait-for-it and wait-for use Bash scripting and other Linux specific utilities.
However, for PHP projects we can avoid using external dependencies and rely on the functionality provided by PHP itself. For example, here is a function to wait for a response from a TCP request to any hostname and port with a configurable timeout:
which can be used to wait for a database server at
mysql on port
3306 with a 10 second timeout:
This can be placed in
wp-config.php of your local development environment or in the
bootstrap.php file of your PHPUnit tests where
mysql can be replaced with known WordPress constant
This also allows us to run
docker-compose run ... commands which are very likely to have some containers still starting up while the target container is already processing the requested command.