I know I’m not the first one to create this and, in fact, there are a plethora of options out there to use as of right now. Still, I wrote my own version of wait-for
, and there are a few differences that make it to be a little more useful than the alternatives.
For those of you who have never heard about this, wait-for
is a very simple and tiny application with a unique purpose: it allows you to define several TCP endpoints – that is, endpoints like a MySQL Database (or MariaDB if you’re in line with the new waves), or even NoSQL ones, like Redis or MongoDB – and wait for them to be ready.
Now ready is a strong word, so to put it in clear terms, wait-for
will wait until a connection can be established against a TCP endpoint, and that’s it, it will allow you to configure some basic automation, needed in environments like docker-compose
or Kubernetes.
The best example is often used in Kubernetes environments where you want to wait for a MariaDB database to be available to connect to it or fail fast if it’s not. The easiest way to do this is by putting this application in an init container and then to probe every second if the database has finally come online.
More Kubernetes-savvy people might work this issue out in different ways, for example:
While those are great arguments against wait-for
, this app is meant to be a stop-gap and not a one-size-fits-all solution. Often teams migrating their apps to Kubernetes environments might not have the time nor the ability to “patch” the application before it makes it to Kubernetes just to implement this feature.
The following YAML, taken as-is from the wait-for
documentation page, outlines a very basic use case scenario:
pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: init-container-demo
spec:
initContainers:
- name: wait-for
image: ghcr.io/patrickdappollonio/wait-for:latest
env:
- name: POSTGRES_HOST
value: "postgres.default.svc.cluster.local:5432"
command:
- /wait-for
args:
- --host="google.com:443"
- --host="mysql.example.com:3306"
- --host="$(POSTGRES_HOST)"
- --verbose
containers:
- name: nginx-container
image: nginx
The highlighted lines above show how to use an init container before the original application starts. In this case, we’re hoping nginx
comes up after. Right before we boot it, we create an init container that pings google.com
on port 443
(for https
), mysql.example.com
on port 3306
, and postgres.default.svc.cluster.local
on port 5432
– note for this last one, the setting is coming as an environment variable fed to the init container.
Out of the box, you can expect:
--host
flag multiple times, and for each, configure the appropriate port.--every
flag.If there are other features you would like to see, please open an issue with your request! Happy to discuss those further!
There are a couple of caveats that I want to wait to see addressed in the open and gauge the interest to know what people would expect here:
scratch
image, and that means there’s no terminal or shell interpreter like bash
or sh
. It’s often, personally, not needed, and you can get environment variable injection from Kubernetes itself as shown above. Still, if there’s a need to have either sh
or bash
, I’m down to hear the recommendations.wait-for -h "example.com:443" -- echo "Success!"
or something along those lines. It gets challenging if you also want a command to execute on failures.wait-for
might not work for your use case. It will 100% work to validate if the database can receive connections, but it will not go through the authentication process – it will close the connection as soon as a socket can be established.Other than that, if you encounter any issues or there’s a feature you would like to see added, please don’t hesitate and open an issue!
Link: wait-for
on Github