Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make my Docker compose "wait-for-it" script invoke the original container ENTRYPOINT or CMD?

Tags:

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?

Test Scenario

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?

like image 545
Derek Mahar Avatar asked May 12 '16 18:05

Derek Mahar


People also ask

Does ENTRYPOINT override CMD in docker?

ENTRYPOINT is the other instruction used to configure how the container will run. Just like with CMD, you need to specify a command and parameters. However, in the case of ENTRYPOINT we cannot override the ENTRYPOINT instruction by adding command-line parameters to the `docker run` command.

Why does docker compose does not wait for container to be ready before moving on to?

There's a good reason for this: 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.

How to make docker compose wait for API container to start?

Here we’ve reverted to only making Docker Compose wait for the api container to start. The web-app service accepts responsibility for checking whether api is healthy. It uses the Wait-for-It script to detect when the container is accessible on port 8080. Wait-for-It will then launch the web app container’s real command, defined as node app.js.

How do I wait for a specific protocol in dockerize?

The dockerize tool gives you the ability to wait for services on a specified protocol ( file, tcp, tcp4, tcp6, http, https and unix) before starting your application: timeout. You can optionally specify how long to wait for the services to become available by using the -timeout # argument (Default: 10 seconds).

What is docker-compose-wait?

It permits to wait for a fixed amount of seconds and/or to wait until a TCP port is open on a target image. Like for the dockerize tool, you need to add the docker-compose-wait tool in your application Dockerfile.

How do I start a docker-compose application in Linux?

The command sh -c “/wait && /sayhello” will run the wait tool and then your application, here /sayhello. When docker-compose is started (or Kubernetes or docker stack or whatever), your application will be started only when all the pairs host:port in the WAIT_HOSTS variable are available.


1 Answers

However, if one uses this option, the container will no longer run its default ENTRYPOINT or CMD command because entrypoint: 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 out CMD defined in Dockerfile

That issue suggests (Jan. 2021)

If you have a custom image you can add a startscript to the build and call it inside the dockerfile and in the docker-compose you can call it again.
Thats a way to avoid duplicate for more complicated entrypoints.

like image 119
VonC Avatar answered Sep 17 '22 19:09

VonC