How to use wait-for-it in docker-compose file?

Viewed 19199

Do I have to first have to clone the wait-for-it repo and edit the parts of the wait-for-it.sh file?

https://github.com/vishnubob/wait-for-it/blob/master/wait-for-it.sh

I'm trying to make my main file fire after 5 seconds after my customer service connects and run its server. (Or whenever customer service connects server properly).

I am aware that in the Dockerfile, we would need to add these commands to it (copying file into workdir, and run the shell script as an executable.)

...
COPY wait-for-it.sh . 
RUN chmod +x /wait-for-it.sh
...

Here's my current Docker-Compose file

version: '3'
services:
  books:
    build: './books'
    container_name: "horus-books"
    ports:
      - "30043:30043"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"

  customers:
    depends_on:
      - books
    build: './customers'
    container_name: "horus-customers"
    ports:
      - "6000:6000"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"

  main:
    depends_on: 
      - customers
    build: './main'
    container_name: "horus-main"
    ports:
      - "4555:4555"
    command: ["./wait-for-it.sh", "customers:6000", "--", "node", "main.js"]
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    

Main Service Dockerfile

FROM node:12.14.0
WORKDIR /usr/src/app
COPY package*.json ./
COPY . /usr/src/app
COPY wait-for-it.sh . 
RUN chmod +x /wait-for-it.sh
RUN npm install
EXPOSE 4555
CMD ["node", "main.js"]
1 Answers

Generally you wouldn't put it in your docker-compose.yml file at all. The script needs to be built into the image, and its standard startup sequence needs to know to run it.

There's a fairly common pattern of using an entrypoint script to do some initial setup, and then use exec "$@" to run the container's command as the main process. This lets you, for example, use the wait-for-it.sh script to wait for the backend to be up, then run whatever the main command happens to be. For example, a docker-entrypoint.sh script might look like:

#!/bin/sh

# Abort on any error (including if wait-for-it fails).
set -e

# Wait for the backend to be up, if we know where it is.
if [ -n "$CUSTOMERS_HOST" ]; then
  /usr/src/app/wait-for-it.sh "$CUSTOMERS_HOST:${CUSTOMERS_PORT:-6000}"
fi

# Run the main container command.
exec "$@"

You need to make sure this script is executable, and make it the image's ENTRYPOINT, but otherwise you can leave the Dockerfile pretty much unchanged.

FROM node:12.14.0
WORKDIR /usr/src/app
COPY package*.json ./
# Do this _before_ copying the entire application in
# to avoid repeating it on rebuild
RUN npm install
# Includes wait-for-it.sh and docker-entrypoint.sh
COPY . ./
RUN chmod +x ./wait-for-it.sh ./docker-entrypoint.sh
EXPOSE 4555
# Add this line
# It _must_ use the JSON-array syntax
ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["node", "main.js"]

In your docker-compose.yml you need to add the configuration to say where the backend is, but you do not need to override command:.

main:
  depends_on: 
    - customers
  build: './main'
  ports:
    - "4555:4555"
  environment:
    - CUSTOMERS_HOST=customers
Related