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.