Home > Software engineering >  Error: Cannot find module '/app/wait-for-it.sh"'
Error: Cannot find module '/app/wait-for-it.sh"'

Time:06-05

I am trying to dockerization my backend server. my stack is nodejs-nestjs with redis and postgres here is my Dockerfile

FROM node:15
WORKDIR /usr/src/app
COPY package*.json ./
COPY tsconfig.json ./
COPY wait-for-it.sh ./
COPY . .
RUN npm install -g [email protected]
RUN npm install
RUN npm run build
RUN chmod  x ./wait-for-it.sh .

EXPOSE 3333
CMD [ "sh", "-c", "npm run start:prod"]

and here is my docker-compose file:

version: '3.2'
services:
  redis-service:
    image: "redis:alpine"
    container_name: redis-container
    ports: 
      - 127.0.0.1:6379:6379
    expose:
      - 6379
  postgres:
    image: postgres:14.1-alpine
    container_name: postgres-container
    restart: always
    environment:
      - POSTGRES_USER=root
      - POSTGRES_PASSWORD=1234
      - DB_NAME = db
    ports:
      - 127.0.0.1:5432:5432
    expose:
      - 5432
    volumes: 
      - db:/var/lib/postgresql/data
  oms-be:
    build: .
    ports:
      - 3333:3333
    links:
      - postgres
      - redis-service
    depends_on:
      - postgres
      - redis-service
    environment:
    - DB_HOST=postgres
    - POSTGRES_PASSWORD = 1234
    - POSTGRES_USER=root
    - AUTH_REDIS_HOST=redis-service
    - DB_NAME = db
    command: ["./wait-for-it.sh", "postgres:5432", "--", "sh", "-c", "npm run start:prod"]
volumes:
  db:
    driver: local

However, when I run docker-compose up I got this error :

taching to oms-be-oms-be-1, postgres-container, redis-container
redis-container     | 1:C 05 Jun 2022 00:35:16.730 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-container     | 1:C 05 Jun 2022 00:35:16.730 # Redis version=7.0.0, bits=64, commit=00000000, modified=0, pid=1, just started
redis-container     | 1:C 05 Jun 2022 00:35:16.730 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis-container     | 1:M 05 Jun 2022 00:35:16.731 * monotonic clock: POSIX clock_gettime
redis-container     | 1:M 05 Jun 2022 00:35:16.731 * Running mode=standalone, port=6379.
redis-container     | 1:M 05 Jun 2022 00:35:16.731 # Server initialized
redis-container     | 1:M 05 Jun 2022 00:35:16.731 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis-container     | 1:M 05 Jun 2022 00:35:16.732 * The AOF directory appendonlydir doesn't exist
redis-container     | 1:M 05 Jun 2022 00:35:16.732 * Ready to accept connections
postgres-container  | 
postgres-container  | PostgreSQL Database directory appears to contain a database; Skipping initialization
postgres-container  | 
postgres-container  | 2022-06-05 00:35:16.824 UTC [1] LOG:  starting PostgreSQL 14.1 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10.3.1_git20211027) 10.3.1 20211027, 64-bit
postgres-container  | 2022-06-05 00:35:16.824 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres-container  | 2022-06-05 00:35:16.824 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres-container  | 2022-06-05 00:35:16.827 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres-container  | 2022-06-05 00:35:16.833 UTC [21] LOG:  database system was shut down at 2022-06-05 00:34:36 UTC
postgres-container  | 2022-06-05 00:35:16.836 UTC [1] LOG:  database system is ready to accept connections
oms-be-oms-be-1     | internal/modules/cjs/loader.js:905
oms-be-oms-be-1     |   throw err;
oms-be-oms-be-1     |   ^
oms-be-oms-be-1     | 
oms-be-oms-be-1     | Error: Cannot find module '/app/wait-for-it.sh"'
oms-be-oms-be-1     |     at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
oms-be-oms-be-1     |     at Function.Module._load (internal/modules/cjs/loader.js:746:27)
oms-be-oms-be-1     |     at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)
oms-be-oms-be-1     |     at internal/main/run_main_module.js:17:47 {
oms-be-oms-be-1     |   code: 'MODULE_NOT_FOUND',
oms-be-oms-be-1     |   requireStack: []
oms-be-oms-be-1     | }
oms-be-oms-be-1 exited with code 1

I tried to build it without wait-for-it.sh and it was complaining that the server cannot connect to the Postgres DB and Redis, so I added wait-for-it.sh file to make it wait until the Redis and the Postgres DB are up, but I got the above error Can anyone tell me what I am doing wrong?

CodePudding user response:

I've simplified your Dockerfile and docker-compose.yaml in order to test things out on my system. I have this package.json:

{
  "name": "example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "echo \"Example build command\"",
    "start:prod": "sleep inf"
  },
  "author": "",
  "license": "ISC"
}

And this Dockerfile:

FROM node:15
WORKDIR /usr/src/app
COPY package*.json ./
COPY wait-for-it.sh ./
RUN chmod  x ./wait-for-it.sh .
RUN npm install
RUN npm run build

EXPOSE 3333
CMD [ "sh", "-c", "npm run start:prod"]

And this docker-compose.yaml:

version: '3.2'
services:
  postgres:
    image: docker.io/postgres:14
    environment:
      POSTGRES_PASSWORD: secret
  oms-be:
    build: .
    ports:
      - 3333:3333
    command: [./wait-for-it.sh", "postgres:5432", "--", "sh", "-c", "npm run start:prod"]

Note that the command: on the final line there has the missing quote. If I try to bring this up using docker-compose up, I see:

oms-be_1    | node:internal/modules/cjs/loader:927
oms-be_1    |   throw err;
oms-be_1    |   ^
oms-be_1    |
oms-be_1    | Error: Cannot find module '/usr/src/app/wait-for-it.sh"'
oms-be_1    |     at Function.Module._resolveFilename (node:internal/modules/cjs/loader:924:15)
oms-be_1    |     at Function.Module._load (node:internal/modules/cjs/loader:769:27)
oms-be_1    |     at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
oms-be_1    |     at node:internal/main/run_main_module:17:47 {
oms-be_1    |   code: 'MODULE_NOT_FOUND',
oms-be_1    |   requireStack: []
oms-be_1    | }

If I correct the syntax so that we have:

version: '3.2'
services:
  postgres:
    image: docker.io/postgres:14
    environment:
      POSTGRES_PASSWORD: secret
  oms-be:
    build: .
    ports:
      - 3333:3333
    command: ["./wait-for-it.sh", "postgres:5432", "--", "sh", "-c", "npm run start:prod"]

Then it runs successfully:

oms-be_1    | wait-for-it.sh: waiting 15 seconds for postgres:5432
oms-be_1    | wait-for-it.sh: postgres:5432 is available after 0 seconds
oms-be_1    |
oms-be_1    | > [email protected] start:prod
oms-be_1    | > sleep inf
oms-be_1    |

The difference in behavior is due to the ENTRYPOINT script in the underlying node:15 image, which includes this logic:

if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ]; then
  set -- node "$@"
fi

That says, essentially:

  • IF the first parameter starts with -
  • OR There is no command matching $1
  • THEN try starting the command with node

With the missing ", you end up with an argument that doesn't match any valid commands, which is why you end up with an error in which node is trying to run the wait-for-it.sh script.

  • Related