0

I'm trying to use wait-for-it in my docker-compose.yaml to wait for mysql to be ready before creating services that are dependent on it. This is my docker-compose.yaml:

version: '3.5'

services:
  mysql:
    image: mysql:5.6
    ports:
      - "3307:3306"
    networks:
      - integration-tests
    environment:
      - MYSQL_DATABASE=mydb
      - MYSQL_USER=root
      - MYSQL_ROOT_PASSWORD=mypassword
    entrypoint: ./wait-for-it.sh mysql:3306
networks:
  integration-tests:
    name: integration-tests

I get this error when trying to run this with docker-compose:

Starting integration-tests_mysql_1 ... error

ERROR: for integration-tests_mysql_1 Cannot start service mysql: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"./wait-for-it.sh\": stat ./wait-for-it.sh: no such file or directory": unknown

ERROR: for mysql Cannot start service mysql: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"./wait-for-it.sh\": stat ./wait-for-it.sh: no such file or directory": unknown ERROR: Encountered errors while bringing up the project.

The wait-for-it.sh script is there on the same level as my docker-compose.yaml file so I don't understand why it's not being found.

gomisha
  • 2,587
  • 3
  • 25
  • 33

2 Answers2

5

Your issue here is that you're trying to execute something that is not part of your image. You're telling docker to create a container from mysql:5.6, which doesn't contain wait-for-it.sh, and then you're telling it to start the container by launching wait-for-it.sh.

I would recommend that you create your own image containing the following:

#Dockerfile
FROM mysql:5.6

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

Then you would replace mysql:5.6 with your image and you should be able to execute wait-for-it.sh. I would also execute it through a command instead of an entrypoint as such:

#docker-compose.yml
...
mysql:
  image: yourmysql:5.6
  command:  bash -c "/wait-for-it.sh -t 0 mysql:3306"
...

Where -t 0 will wait for mysql without a timeout.

twoTimesAgnew
  • 1,376
  • 1
  • 11
  • 15
  • Thanks! This would mean I now have to create a separate image for that specific version of mysql just because I want to run wait-for-it.sh. And when I want to run a newer version of mysql, I'd have to make a totally new Docker image just so I can run that script. Seems like overkill. I've got multiple dependency services that I want to wait for before my main app starts and this would add a lot of overhead. Is there no way to run that script without creating a separate image? – gomisha Oct 10 '18 at 18:45
  • You're right, it does add overhead, but it's the right way to do it. Another option would be to create a volume bind to essentially mount your code, and while that's a valid solution in a dev environment, you wouldn't want that in production. Using your own images gives you more control over your application. Even though you might only be using default images for now, down the line you might need to add more functionalities/modules/whatever else. You can check this [link](https://github.com/vishnubob/wait-for-it/issues/57) from the official repo of wait-for-it.sh – twoTimesAgnew Oct 10 '18 at 19:12
  • After a bit of research, I just found that there might be a new way to achieve this that I wasn't aware of. Depends_on can now use healthcheck conditions. Check out this [article](https://til.codes/health-check-option-in-docker-to-wait-for-dependent-containers-to-be-healthy/) and if you end up getting it to work with your use case, I'd be interested in hearing about it! – twoTimesAgnew Oct 10 '18 at 19:23
  • Yes, I saw the health check approach too. That article uses postgres. I couldn't find a health check test that works for mysql. Have a look at https://stackoverflow.com/questions/42567475/docker-compose-check-if-mysql-connection-is-ready. – gomisha Oct 10 '18 at 20:10
1

You can control services startup order by using the docker depends_on option.

Mr3381
  • 367
  • 4
  • 10
  • 4
    Yes, I knew about depends_on but the problem with it is that it doesn't wait for a dependent service to be started before starting the next service. That's why I was trying to use wait-for-it. – gomisha Nov 26 '18 at 10:35