"wait-for", a tiny utility to wait for TCP resources to be ready
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:
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
mysql.example.com on port
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:
--hostflag multiple times, and for each, configure the appropriate port.
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:
scratchimage, and that means there’s no terminal or shell interpreter like
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
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-formight 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!
wait-for on Github