-2

Im trying to figure out how to properly use the command key word in a docker-compose.yml

Im trying to execute the following commands:

  1. cd ./wait-for-it
  2. wait-for-it.sh postgres:5432
  3. cd
  4. cd ./api
  5. yarn start

I can structure it like this

command: ["./wait-for-it/wait-for-it.sh", "postgres:5432", "--", "yarn", "start"]

However I don't know how to cd into api before doing yarn

Any thoughts on how to structure the command properly?

lucas rodriguez
  • 980
  • 2
  • 8
  • 20
  • Isn't the problem that you have a bare `cd` in the middle? – jonrsharpe Apr 25 '20 at 15:42
  • nop that brings me back to the home directory modifying to make clearer – lucas rodriguez Apr 25 '20 at 15:43
  • Ah interesting, TIL. Do you know which *part* of that command fails then? What container is it running in? You could also try the `--cwd` flag to Yarn. – jonrsharpe Apr 25 '20 at 15:45
  • Further edit, Its no currently failing im just missing a part of the command, executing the `yarn` from `./api` instead of the woking directory – lucas rodriguez Apr 25 '20 at 15:49
  • Does this answer your question? [Run yarn in a different path](https://stackoverflow.com/questions/46891622/run-yarn-in-a-different-path) – jonrsharpe Apr 25 '20 at 15:51
  • This doesnt seem to work unfotunately, I get an error saying the directory doesn't exist but running: `command: ["./wait-for-it/wait-for-it.sh", "postgres:5432", "--", "./api","yarn", "start"]` returns `./api is a directory` – lucas rodriguez Apr 25 '20 at 15:59

1 Answers1

1

The absolute best way to manage complex startup commands like this is to (a) write them as shell scripts and (b) bake them into your Docker image.

For instance, I can reinterpret the startup procedure that you wrote as pseudocode like:

1. cd into the wait-for-it directory and run the wait-for-it script
2. Do the thing the container was originally going to do

I can translate that into a shell script:

#!/bin/sh
(cd /app/wait-for-it && ./wait-for-it.sh "$DB_HOST_PORT")
exec "$@"

Then I can use that script as an ENTRYPOINT in my image. It runs the cd command in a subshell so it returns back to the original directory on the next line; the exec "$@" line runs what was passed as a command. The end of your Dockerfile would look like:

COPY entrypoint.sh /app
RUN chmod +x entrypoint.sh

WORKDIR /app/api
ENTRYPOINT ["/app/entrypoint.sh"]
CMD ["yarn", "start"]

Then I don't need to manually override these settings in the docker-compose.yml at all; the only thing I need to do is to provide the database location as an environment variable.

version: '3'
services:
  myapp:
    build: .
    environment:
      - DB_HOST_PORT=postgres:5432
    ports:
      - '3000:3000'
  postgres:
    image: postgres:12

If I wanted to run some other command:

docker-compose run myapp yarn migrate

It would still wait for the database to be available, but then run the alternate command.

David Maze
  • 130,717
  • 29
  • 175
  • 215