According to Controlling startup order in Compose, one can control the order in which Docker Compose starts containers by using a "wait-for-it" script. Script wait-for-it.sh
expects both a host:port
argument as well as the command that the script should execute when the port is available. The documentation recommends that Docker Compose invoke this script using the entrypoint:
option. However, if one uses this option, the container will no longer run its default ENTRYPOINT
or CMD
because entrypoint:
overrides the default.
How might one provide this default command to wait-for-it.sh
so that the script can invoke the default ENTRYPOINT
or CMD
when the condition for which it waits is satisfied?
In my case, I've implemented a script wait-for-file.sh
that polls waiting for a file to exist:
#!/bin/bash
set -e
waitFile="$1"
shift
cmd="$@"
until test -e $waitFile
do
>&2 echo "Waiting for file [$waitFile]."
sleep 1
done
>&2 echo "Found file [$waitFile]."
exec $cmd
Docker Compose invokes wait-for-file.sh
as the entry-point to a slightly custom container derived from tomcat:8-jre8
:
platinum-oms:
image: opes/platinum-oms
ports:
- "8080:8080"
volumes_from:
- liquibase
links:
- postgres:postgres
- activemq:activemq
depends_on:
- liquibase
- activemq
entrypoint: /wait-for-file.sh /var/run/liquibase/done
Before it exits successfully, another custom container liquibase
creates /var/run/liquibase/done
and so platinum-oms
effectively waits for container liquibase
to complete.
Once container liquibase
creates file /var/run/liquibase/done
, wait-for-file.sh
prints Found file [/var/run/liquibase/done].
, but fails to invoke default command catalina.sh run
in base container tomcat:8-jre8
. Why?
I created a simplified test scenario docker-compose-wait-for-file
to demonstrate my problem. Container ubuntu-wait-for-file
waits for container ubuntu-create-file
to create file /wait/done
and then I expect container ubuntu-wait-for-file
to invoke the default ubuntu
container command /bin/bash
, but instead, it exits. Why doesn't it work as I expect?
However, if one uses this option, the container will no longer run its default
ENTRYPOINT
orCMD
command becauseentrypoint:
overrides the default.
That is expected, which is why the wait-for-it
is presented as a wrapper script.
It does allow to execute a "subcommand" though:
wait-for-it.sh host:port [-s] [-t timeout] [-- command args]
^^^^^^^^^^^^
The subcommand will be executed regardless if the service is up or not.
If you wish to execute the subcommand only if the service is up, add the--strict
argument.
That means the CMD
part of your image can be used for your actual container command, as its parameters will passed in parameters to the ENTRYPOINT
command:
entrypoint: wait-for-it.sh host:port --
cmd: mycmd myargs
This should work... except for docker-compose
issue 3140 (mentioned by the OP Derek Mahar in the comments)
entrypoint defined in
docker-compose.yml
wipes outCMD
defined in Dockerfile