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.
