vishnubob / wait-for-it

Pure bash script to test and wait on the availability of a TCP host and port
MIT License
9.37k stars 2.28k forks source link

Usage with Docker #57

Open agustisanchez opened 6 years ago

agustisanchez commented 6 years ago

In order to use it with Docker and docker-compose, place it alongside Dockerfile, build it into the image with exec permissions and reference it in docker-compose.yml.

- Dockerfile
- wait-for-it.sh
#Dockerfile
...
COPY wait-for-it.sh /wait-for-it.sh
RUN chmod +x /wait-for-it.sh
...
#docker-compose.yml
...
  my-service:
    build:
      context: "."
      container_name: my_container
      command: ["/wait-for-it.sh", "mysql:3306", "--", [entrypoint function]]
...
douglas-gibbons commented 5 years ago

Thanks @agustisanchez - I like it. Depending on your setup, you might also copy wait-for-it.sh in as a mounted volume, such as this:

version: '3'

services:
  hello-world:
    image: ubuntu
    volumes:
      - ./wait-for-it.sh:/usr/local/bin/wait-for-it.sh
    command:
      - wait-for-it.sh
      - github.com:80
      - --
      - echo
      - "hello world"
portolkyz commented 5 years ago

Depending on the base image used there will be no netcat available in the container. The description pure bash conflicts in this case with the fact that netcat is no shell builtin. No offense intended.

Cheers

Tux1234 commented 5 years ago

Can you tell me what my Entrypoint is? Given are the following snippets.

Dockerfile

FROM java:8
VOLUME /tmp
EXPOSE 8080
COPY wait-for-mysql.sh /wait-for-mysql.sh
RUN chmod +x /wait-for-mysql.sh
ADD target/App.jar App.jar.
ENTRYPOINT ["java","-jar","App.jar"]

Im not shure with my ENTRYPOINT. I do the follwoing.

docker-compose.yml

...
  mysql-docker-container:
  ..
  .
  my-service:
    build:
      context: "."
      container_name: my_container
      command: ["./wait-for-mysql.sh", "mysql-docker-container:3306", "--", "java", "App.jar"]
....

Is the Entrypoint correct?

Calimerico commented 5 years ago

I think that your command should look like this: command: ["./wait-for-mysql.sh", "mysql-docker-container:3306", "--", "sh", "-c", "java", "App.jar"]

alexgivi commented 5 years ago

to find out what is default entrypoint - do next steps:

  1. comment entrypoint config line in docker-compose.yml
  2. start service (docker-compose up -d)
  3. inspect service (docker inspect my_container) and find info about entrypoint. also it's possible to view entrypoint via docker ps, but string is truncated.
  4. modify your entrypoint: "wait-for-it mysql-docker-container:3306 -- default-entrypoint", replace "default-entrypoint" to your actual command
yaoyuanyy commented 5 years ago

In order to use it with Docker and docker-compose, place it alongside Dockerfile, build it into the image with exec permissions and reference it in docker-compose.yml.

- Dockerfile
- wait-for-it.sh
#Dockerfile
...
COPY wait-for-it.sh /wait-for-it.sh
RUN chmod +x /wait-for-it.sh
...
#docker-compose.yml
...
  my-service:
    build:
      context: "."
      container_name: my_container
      command: ["/wait-for-it.sh", "mysql:3306", "--", [entrypoint function]]
...

@agustisanchez what is the "entrypoint function" in docker-compose.yml

yaoyuanyy commented 5 years ago

@agustisanchez if i want to run a java project, what is the "entrypoint function"

alexgivi commented 5 years ago

https://docs.docker.com/compose/compose-file/#command https://docs.docker.com/compose/compose-file/#entrypoint there is some difference between command and entrypoint. personally I prefer to use entrypoint config and don't use command.

jakzal commented 5 years ago

Multistage builds can be leveraged to install wait-for-it with apt-get:

FROM debian:buster-slim as wait-for-it
RUN apt-get update && apt-get install -y "wait-for-it"

FROM debian:buster-slim
COPY --from=wait-for-it /usr/bin/wait-for-it /usr/bin/wait-for-it

If there was an official docker image for wait-for-it (i.e. wait-for-it/wait-for-it) we could potentially do:

FROM debian:buster-slim
COPY --from=wait-for-it/wait-for-it /usr/bin/wait-for-it /usr/bin/wait-for-it
kunal-bhatia commented 5 years ago

@douglas-gibbons Is it possible to use it with google distroless java images?

mdkalish commented 4 years ago

For a dependency that you don't need to build (i.e. also create Dockerfile and specify context), you can make it work with the volumes config only:

  1. chmod 755 wait-for-it.sh
  2. # docker-compose.yml
    …
    volumes:
    - "./wait-for-it.sh:/wait-for-it.sh:ro"
    …

Good to know:

ncjones commented 4 years ago

wait-for-it.sh is not trapping SIGTERM so, to be able to gracefully stop a service that is stuck waiting, the stop signal needs to be overridden in docker-compose.yml:

version: '3'

services:
  wait-for-app:
    image: ubuntu
    volumes:
      - ./wait-for-it.sh:/usr/local/bin/wait-for-it.sh
    command: wait-for-it.sh app:8080 -- echo ok
    stop_signal: SIGINT
97lynk commented 4 years ago

I want to share my case. I investigated.

I using openjdk:8-jdk-alpine image docker. My environment:

My Dockerfile

FROM openjdk:8-jdk-alpine

RUN apk add --no-cache bash

COPY ./wait-for-it.sh /wait-for-it.sh

RUN chmod +x wait-for-it.sh

RUN ls -la

and used it in docker-compose.yml file command: bash ./wait-for-it.sh my-service:8080 --strict -- java -jar app.jar But it was failed!!! @@

This issue is EOL(end of line). My _wait_forit.sh file has CRLF (windows). I changed it into LF (for Unix and MacOs). It worked!

SandeepYadav-Hashedin commented 4 years ago

I want to share my case. I investigated.

I using openjdk:8-jdk-alpine image docker. My environment:

  • OS: window 10 Pro
  • Docker engine: 19.03.2

My Dockerfile

FROM openjdk:8-jdk-alpine

RUN apk add --no-cache bash

COPY ./wait-for-it.sh /wait-for-it.sh

RUN chmod +x wait-for-it.sh

RUN ls -la

and used it in docker-compose.yml file command: bash ./wait-for-it.sh my-service:8080 --strict -- java -jar app.jar But it was failed!!! @@

This issue is EOL(end of line). My _wait_forit.sh file has CRLF (windows). I changed it into LF (for Unix and MacOs). It worked!

Thanks, this really helped, I had spent hours figuring out why it's not working for me despite putting all the commands correctly. Changing from CRLF to LF worked like a charm.

Choongkyu commented 3 years ago

is there a way to retain the CMD in the Dockerfile so other users can easily opt-out of using docker-compose?

johntheprime commented 3 years ago

I struggled with this problem for a long time and finally come up with a solution with reference from above. In case someone would come here for solutions, here is my working codes.

In your Dockerfile, you would add this for the wait-for-it.sh. The $APP_HOME is an ENV variable that you might define after FROM command for your specific project.

COPY wait-for-it.sh $APP_HOME/app

WORKDIR $APP_HOME/app

RUN chmod +x wait-for-it.sh

ENTRYPOINT ["/bin/bash", "-c"]

In your docker-compose.yml, you might add the following:

app:
  restart: on-failure
  command: ["./wait-for-it.sh db:3306 --strict --timeout=300 -- alembic upgrade head && python main.py"]

Note all the rest configurations were not mentioned here, but they could be found from other references as above.