Problem about dockerizing a NestJS app with Prisma and PostgreSQL - node.js

I am trying to build a NestJS app with Prisma and PostgreSQL. I want to use docker; however, I got an error when I sent the request to the backend.
Here is my docker file
FROM node:14 AS builder
WORKDIR /app
COPY package*.json ./
COPY prisma ./prisma/
RUN npm install
RUN npx prisma generate
COPY . .
RUN npm run build
FROM node:14
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD [ "npm", "run", "start:prod" ]
Here is my docker-compose.yml
version: '3.8'
services:
nest-api:
container_name: nest-api
build:
context: .
dockerfile: Dockerfile
ports:
- 3000:3000
depends_on:
- postgres
env_file:
- .env
postgres:
image: postgres:13
container_name: postgres
restart: always
ports:
- 5432:5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: task-management
env_file:
- .env
Here is my schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
//url = "postgresql://postgres:postgres#localhost:5432/task-management?schema=public"
}
model Task {
id Int #id #default(autoincrement())
title String
description String
status TaskStatus #default(OPEN)
}
enum TaskStatus {
OPEN
IN_PRO
DOooNE
}
Here is the .env
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server and MongoDB (Preview).
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL=postgresql://postgres:postgres#postgres:5432/task-management?schema=public
After I run the command:docker-compose up, everything is fine. However, if I send the request to the app, I get the following error:
nest-api | [Nest] 19 - 11/02/2021, 5:52:43 AM ERROR [ExceptionsHandler]
nest-api | Invalid `this.prisma.task.create()` invocation in
nest-api | /dist/tasks/tasks.service.js:29:33
nest-api |
nest-api | 26 return found;
nest-api | 27 }
nest-api | 28 async creatTask(data) {
nest-api | → 29 return this.prisma.task.create(
nest-api | The table `public.Task` does not exist in the current database.
nest-api | Error:
nest-api | Invalid `this.prisma.task.create()` invocation in
nest-api | /dist/tasks/tasks.service.js:29:33
nest-api |
nest-api | 26 return found;
nest-api | 27 }
nest-api | 28 async creatTask(data) {
nest-api | → 29 return this.prisma.task.create(
nest-api | The table `public.Task` does not exist in the current database.
nest-api | at cb (/node_modules/#prisma/client/runtime/index.js:38537:17)
nest-api | at async /node_modules/#nestjs/core/router/router-execution-context.js:46:28
nest-api | at async /node_modules/#nestjs/core/router/router-proxy.js:9:17
What changes should I make in the docker file to solve the problem?

Related

Unable to connect nodejs app to mongodb using docker-compose

Simple Node app and mongo containers created using docker-compose below... What am I missing?
mongodb://user:password#mongo:27017/
version: '3.8'
services:
mongo:
image: mongo
restart: always
environment:
- MONGO_INITDB_ROOT_USERNAME=user
- MONGO_INITDB_ROOT_PASSWORD=password
app:
image: app
build:
context: ./app
dockerfile: Dockerfile
ports:
- "3000:3000"
depends_on:
- mongo
I've read several posts on the same issue and the official mongo docker page and seem to be doing everything correct. Keep getting the following msg.
app_1 | mongodb://user:password#mongo:27017/ {
app_1 | autoIndex: false,
app_1 | poolSize: 10,
app_1 | bufferMaxEntries: 0,
app_1 | useNewUrlParser: true,
app_1 | useUnifiedTopology: true
app_1 | }
app_1 | MongoDB connection with retry
app_1 | MongoDB connection unsuccessful, retry after 5 seconds. 2
I prepared interesting test for you
version: '3.8'
services:
mongo:
image: mongo
environment:
- MONGO_INITDB_ROOT_USERNAME=user
- MONGO_INITDB_ROOT_PASSWORD=password
healthcheck:
test: "echo 'db.runCommand(\"ping\").ok'"
interval: 5s
timeout: 5s
retries: 3
app:
image: mongo
command: "mongosh mongodb://user:password#mongo:27017/admin --eval \"printjson(db.test.insertOne({'a': 1}))\""
ports:
- "3000:3000"
depends_on:
- mongo
It will print
app_1 | {
app_1 | acknowledged: true,
app_1 | insertedId: ObjectId("63696c4e99703eb4ab9fba62")
app_1 | }
but if you will change
command: "mongosh mongodb://user:password#mongo:27017/admin --eval \"printjson(db.test.insertOne({'a': 1}))\""
to
command: "mongosh mongodb://user:password#mongo:27017/local --eval \"printjson(db.test.insertOne({'a': 1}))\""
you will see error. Even if you will add MONGO_INITDB_DATABASE to mongo with value local.
You can test it running in second console command:
docker-compose run app bash
and then try
mongosh mongodb://user:password#mongo:27017/admin --eval "printjson(db.test.insertOne({'a': 1}))"
with success
and
mongosh mongodb://user:password#mongo:27017/local --eval "printjson(db.test.insertOne({'a': 1}))"
that failing. You can see logs from mongo like
mongo_1 | {"t":{"$date":"2022-11-07T20:40:35.686+00:00"},"s":"I", "c":"ACCESS", "id":20249, "ctx":"conn6","msg":"Authentication failed","attr":{"mechanism":"SCRAM-SHA-256","speculative":true,"principalName":"user","authenticationDatabase":"local","remote":"172.20.0.3:50382","extraInfo":{},"error":"UserNotFound: Could not find user \"user\" for db \"local\""}}
mongo_1 | {"t":{"$date":"2022-11-07T20:40:35.687+00:00"},"s":"I", "c":"ACCESS", "id":20249, "ctx":"conn6","msg":"Authentication failed","attr":{"mechanism":"SCRAM-SHA-1","speculative":false,"principalName":"user","authenticationDatabase":"local","remote":"172.20.0.3:50382","extraInfo":{},"error":"UserNotFound: Could not find user \"user\" for db \"local\""}}
mongo_1 | {"t":{"$date":"2022-11-07T20:40:35.688+00:00"},"s":"I", "c":"NETWORK", "id":22944, "ctx":"conn5","msg":"Connection ended","attr":{"remote":"172.20.0.3:50374","uuid":"b77fff1f-b832-4900-9c2d-1e7fd1e79424","connectionId":5,"connectionCount":1}}
mongo_1 | {"t":{"$date":"2022-11-07T20:40:35.699+00:00"},"s":"I", "c":"NETWORK", "id":22944, "ctx":"conn6","msg":"Connection ended","attr":{"remote":"172.20.0.3:50382","uuid":"3995bcbf-706d-4bed-92a2-04736305b7c2","connectionId":6,"connectionCount":0}}
this problem is described in topic User not found on MongoDB Docker image with authentication
You can authenticate with user,password against admin db, not mydb
You can read more about creating database with user and password here:
How to create a DB for MongoDB container on start up?

Differences in code between local project and Dockerized project break the app

I'm trying to dockerize my current pet project in which I use a NodeJS (ExpressJS) as a backend, React as a frontend and PostgreSQL as a database. On both backend and frontend I use TypeScript instead of JavaScript. I'm also using a Prisma as ORM for my database. I decided to have a standard three container's architecture, one for backend, one for database and one for frontend app. My Dockerfile's are as follows:
Frontend's Dockerfile
FROM node:alpine
WORKDIR /usr/src/frontend
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "run", "start"]
Backend's Dockerfile
FROM node:lts
WORKDIR /usr/src/backend
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8000
RUN npx prisma generate
CMD ["npm", "run", "dev"]
there's also a .dockerignore file in the backend folder:
node_modules/
and my docker-compose.yml looks like this:
version: '3.9'
services:
db:
image: 'postgres'
ports:
- '5432:5432'
environment:
POSTGRES_USER: 'postgres'
POSTGRES_PASSWORD: 'postgres'
POSTGRES_DB: 'hucuplant'
server:
build:
context: ./backend_express
ports:
- "8000:8000"
environment:
DATABASE_URL: 'postgresql://postgres:postgres#localhost:5432/hucuplant?schema=public'
client:
build:
context: ./frontend
ports:
- "3000:3000"
After doing a docker-compose up --build everything starts well but when I try to register a new user on my site then I get the following error:
Error:
hucuplant-server-1 | Invalid `prisma.user.findUnique()` invocation in
hucuplant-server-1 | /usr/src/backend/src/routes/Auth.ts:44:57
hucuplant-server-1 |
hucuplant-server-1 | 41 auth.post("/register", async (req: Request, res: Response) => {
hucuplant-server-1 | 42 const { email, username, password } = req.body;
hucuplant-server-1 | 43
hucuplant-server-1 | → 44 const usernameResult: User | null = await prisma.user.findUnique({
hucuplant-server-1 | where: {
hucuplant-server-1 | ? username?: String,
hucuplant-server-1 | ? id?: Int,
hucuplant-server-1 | ? email?: String
hucuplant-server-1 | }
hucuplant-server-1 | })
However, the existing code in my Auth.ts file on the line 44 looks like this:
auth.post("/register", async (req: Request, res: Response) => {
const { email, username, password } = req.body;
const usernameResult: User | null = await prisma.user.findUnique({
where: {
username: username,
},
});
When I run my project locally everything works just fine but when I try to run the containerized app then those things break and differ quite much. What is causing that? How do I fix that?

my puppeteer not working on docker container

It was working fine on just development environment not docker container.
But not working on docker container. How do I setup puppeteer on docker container?
I have seen a lot of answer and question but not working at all. I think that my code is wrong..
My Env:
OS: MacOS, M1
Here is Dockerfile:
FROM node:18-alpine
WORKDIR /usr/src/app
RUN apk update && apk upgrade
RUN apk add --no-cache udev ttf-freefont chromium
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true \
CHROME_PATH=/usr/bin/chromium-browser \
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 8120
CMD ["npm", "run", "start:dev"]
And docker-compose.yml:
version: "3.7"
services:
node:
container_name: node-test
build:
context: .
dockerfile: Dockerfile
restart: always
platform: linux/amd64
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- test-net
env_file:
- .env
ports:
- "8010:8010"
depends_on:
- mongo
mongo:
image: mongo
container_name: mongo
restart: always
networks:
- test-net
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: test
MONGO_INITDB_ROOT_PASSWORD: test
MONGO_INITDB_DATABASE: test
volumes:
mongo:
networks:
test-net:
name: test-net
external: true
crawler.ts:
import puppeteer from 'puppeteer';
export const crawler = async (url: string) => {
console.log(url); // <- [v] working
const browser = await puppeteer.launch({
ignoreHTTPSErrors: false,
executablePath: '/usr/bin/chromium-browser',
headless: true,
args:
'--disable-dev-shm-usage',
'--no-sandbox',
'--disable-setuid-sandbox'
],
slowMo: 30
});
console.log(browser) // [v] print something.
const page = await browser.newPage();
console.log(page); // <- [x] not working. print anything.
await page.setViewport({ width: 1920, height: 1080 })
await page.goto("https://www.example.com");
await page.close();
await browser.close();
};
My error message is different whenever modify my code, but It is latest error message on terminal.
node-test | ProtocolError: Protocol error (Target.createTarget): Target closed.
node-test | at /usr/src/app/node_modules/puppeteer/src/common/Connection.ts:119:16
node-test | at new Promise (<anonymous>)
node-test | at Connection.send (/usr/src/app/node_modules/puppeteer/src/common/Connection.ts:115:12)
node-test | at Browser._createPageInContext (/usr/src/app/node_modules/puppeteer/src/common/Browser.ts:525:47)
node-test | at BrowserContext.newPage (/usr/src/app/node_modules/puppeteer/src/common/Browser.ts:886:26)
node-test | at Browser.newPage (/usr/src/app/node_modules/puppeteer/src/common/Browser.ts:518:33)
node-test | at crawler (/usr/src/app/src/crawler/crawler.ts:16:30)
node-test | at processTicksAndRejections (node:internal/process/task_queues:95:5)
node-test | at async CrawlerController (/usr/src/app/src/crawler/crawler.controller.ts:10:5) {
node-test | originalMessage: ''
node-test | }

prisma can't find database url

I'm using Prisma in node and I'm using docker.
When I try to create a new user in my database, it says that DATABASE_URL was not found but I declared it inside my env so I don't really know where I have this error.
server_container | Server is running on port 4000
server_container |
server_container | Invalid `prisma.user.create()` invocation in
server_container | /app/src/app.ts:18:36
server_container |
server_container | 15 const prisma = new PrismaClient();
server_container | 16
server_container | 17 const main = async () => {
server_container | → 18 const user = await prisma.user.create(
server_container | error: Environment variable not found: DATABASE_URL.
server_container | --> schema.prisma:10
server_container | |
server_container | 9 | provider = "postgresql"
server_container | 10 | url = env("DATABASE_URL")
server_container | |
server_container |
server_container | Validation Error Count: 1
My docker docker-compose.yml looks like that:
version: '3.8'
services:
api:
build: .
container_name: server_container
ports:
- "4000:4000"
volumes:
- ./:/app
networks:
- api-pokemon-network
depends_on:
- db
db:
image: postgres:14
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_PORT: ${POSTGRES_PORT}
volumes:
- data:/var/lib/postgresql/data
env_file:
- .env
command: -p ${POSTGRES_PORT}
networks:
- api-pokemon-network
ports:
- '${POSTGRES_PORT}:${POSTGRES_PORT}'
volumes:
data:
networks:
api-pokemon-network:
and this is my .env
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres_docker
POSTGRES_HOST=db
POSTGRES_PORT=54320
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}#localhost:${POSTGRES_PORT}/${POSTGRES_DB}?schema=public
just run npx prisma generate. This will re-establish the link between schema.prisma and .env file.Make sure you make your DBURL within the backticks ``.

(Docker-Compose) UnhandledPromiseRejectionWarning when connecting node and postgres

I am trying to connect the containers for postgres and node. Here is my setup:
yml file:
version: "3"
services:
postgresDB:
image: postgres:alpine
container_name: postgresDB
ports:
- "5432:5432"
environment:
- POSTGRES_DB=myDB
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=Thisisngo1995!
express-server:
build: ./
environment:
- DB_SERVER=postgresDB
links:
- postgresDB
ports:
- "3000:3000"
Dockerfile:
FROM node:12
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY . .
COPY ormconfig.docker.json ./ormconfig.json
EXPOSE 3000
CMD ["npm", "start"]
connect to postgres:
let { Pool, Client } = require("pg");
let postgres = new Pool({
host: "postgresDB",
port: 5432,
user: "postgres",
password: "Thisisngo1995!",
database: "myDB",
});
module.exports = postgres;
and here is how I handled my endpoint:
exports.postgres_get_controller = (req, resp) => {
console.log("Reached Here");
postgres
.query('SELECT * FROM public."People"')
.then((results) => {
console.log(results);
resp.send({ allData: results.rows });
})
.catch((e) => console.log(e));
};
Whenever I try to touch the endpoint above, I get this error in the container:
Reasons why?
Note: I am able to have everything functioning on my local machine (without docker) simply by changing "host: localhost"
Your postgres database name and username should be the same
You can use docker-compose-wait to make sure interdependent services are launched in proper order.
See below on how to use it for your case.
update the final part of your Dockerfile as below;
# ...
# this will be used to check if DB is up
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.7.3/wait ./wait
RUN chmod +x ./wait
CMD ./wait && npm start
Update some parts of your docker-compose.yml as below:
express-server:
build: ./
environment:
- DB_SERVER=postgresDB
- WAIT_HOSTS=postgresDB:5432
- WAIT_BEFORE_HOSTS=4
links:
- postgresDB
depends_on:
- postgresDB
ports:
- "3000:3000"

Resources