DEV Community

Cover image for Dockerize Nestjs app with Postgres + Redis + Prisma ORM
Manuchehr
Manuchehr

Posted on

Dockerize Nestjs app with Postgres + Redis + Prisma ORM

We're about to embark on an epic journey into the world of containerization. In this guide, we'll be turning a regular NestJS app into a Dockerized powerhouse, complete with PostgreSQL, Redis, and the magic touch of Prisma ORM.

First of all we should create Dockerfile:

FROM node:18-alpine  

WORKDIR /usr/src/app  

COPY package*.json ./  
COPY entrypoint.sh ./  

RUN npm install  

COPY . .

RUN chmod +x /usr/src/app
RUN chmod +x /usr/src/app/entrypoint.sh

RUN npx prisma generate --schema=/usr/src/app/src/database/schema.prisma  

RUN npm run build

ENTRYPOINT ["/usr/src/app/entrypoint.sh", "npm", "run", "start:prod"]  

CMD ["npm", "run", "start:prod"]
Enter fullscreen mode Exit fullscreen mode
  1. FROM node:18-alpine - This line sets the base image for the Docker image. It specifies that the image should be based on the official Node.js 18 Alpine image. Alpine is a lightweight Linux distribution, making the resulting Docker image smaller.

  2. WORKDIR /usr/src/app - This line sets the working directory inside the container to /usr/src/app. Subsequent commands will be executed from this directory.

  3. COPY package*.json ./ - Copies the package.json and package-lock.json files from the host machine to the /usr/src/app directory inside the container. This allows for efficient installation of Node.js dependencies.

  4. COPY entrypoint.sh ./ - Copies the entrypoint.sh script from the host machine to the /usr/src/app directory inside the container. This script might be used to perform additional setup or configuration before starting the application.

  5. RUN npm install - Executes the npm install command inside the container, installing the Node.js dependencies specified in the package.json file. This step is crucial for setting up the application environment.

  6. COPY . ./ - Copies the entire application source code from the host machine to the /usr/src/app directory inside the container. This includes all the application files, not just the package.json and package-lock.json files.

  7. RUN npx prisma generate --schema=/usr/src/app/src/database/schema.prisma - Executes the Prisma CLI command to generate Prisma client code based on the schema defined in /usr/src/app/src/database/schema.prisma. This step is specific to Prisma and is part of the database setup.

  8. RUN npm run build - Executes the npm run build command inside the container. This command is often used to compile TypeScript code or perform other build-related tasks for the Node.js application.

  9. ENTRYPOINT ["/usr/src/app/entrypoint.sh", "npm", "run", "start:prod"] - Specifies the default command to run when the container starts. In this case, it uses the entrypoint.sh script followed by the command npm run start:prod. The entrypoint.sh script handles additional setup before running the application.

  10. CMD ["npm", "run", "start:prod"] - Provides a default command to run when the container starts if no other command is specified. This is overridden by the ENTRYPOINT command. Here, it's set to run npm run start:prod.

by following .dockerignore file:

Dockerfile  
.dockerignore  
node_modules  
npm-debug.log  
dist  
Enter fullscreen mode Exit fullscreen mode

You should also create entrypoint.sh this file is executed once docker image is started to make prisma migrations:

#!/bin/sh  

# Apply Prisma migrations and start the application  
npx prisma migrate deploy --schema=/usr/src/app/src/database/schema.prisma  
npx prisma generate --schema=/usr/src/app/src/database/schema.prisma  

# Run database migrations  
npx prisma migrate dev --name init --schema=/usr/src/app/src/database/schema.prisma

# Run the main container command  
exec "$@"
Enter fullscreen mode Exit fullscreen mode

Attention! You should specify the path of your prisma.schema file.

Create a docker-compose.yml file:

version: "3"  

services:  
  app:    
    container_name: "myapp_web_app"  
    restart: unless-stopped  
    build:  
      context: .  
      dockerfile: Dockerfile  
    environment:  
      PORT: ${PORT}  
      POSTGRES_HOST: postgres_db # localhost doesn't work in docker container, hence you should use postgres container name instead of localhost
      REDIS_HOST: redis # the same for redis. Use redis container name instead of localhost
    ports:
      - ${PORT}:${PORT}  
    depends_on:  
      - postgres_db  
      - redis  
    networks:  
      myapp_net:

  postgres_db:    
    image: bitnami/postgresql:15  
    container_name: "myapp_postgres_db"  
    restart: unless-stopped  
    environment:  
      POSTGRESQL_USERNAME: ${POSTGRES_USER}  
      POSTGRESQL_PASSWORD: ${POSTGRES_PASSWORD}  
      POSTGRESQL_DATABASE: ${POSTGRES_DB}  
      POSTGRESQL_TIMEZONE: "Asia/Tashkent" # This is optional
    ports:
      - ${POSTGRES_PORT}:5432  
    volumes:  
      - "postgres_data:/bitnami/postgresql"  
    networks:  
      myapp_net:  
  redis:    
    image: "bitnami/redis:7.2"  
    container_name: "myapp_redis"  
    restart: unless-stopped  
    ports:  
      - ${REDIS_PORT}:${REDIS_PORT}  
    volumes:  
      - "redis_data:/bitnami/redis/data"  
    environment:  
      REDIS_PASSWORD: ${REDIS_PASSWORD}  
      REDIS_PORT: ${REDIS_PORT}  
      REDIS_DB: ${REDIS_DB}  
      REDIS_IO_THREADS: 4  
      REDIS_IO_THREADS_DO_READS: yes  
      REDIS_DISABLE_COMMANDS: FLUSHDB,FLUSHALL  
    networks:  
      myapp_net: 

volumes:  
  postgres_data:  
  redis_data:  

networks:  
  myapp_net:
Enter fullscreen mode Exit fullscreen mode

This is my .env file:

PORT=9000
# Postgres
POSTGRES_DB=sampledb  
POSTGRES_HOST=localhost  
POSTGRES_PORT=5432  
POSTGRES_USER=username  
POSTGRES_PASSWORD=password  
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?schema=public
# Redis
REDIS_HOST=localhost  
REDIS_PORT=6379  
REDIS_PASSWORD=veryhardpassword  
REDIS_DB=0
Enter fullscreen mode Exit fullscreen mode

Run docker compose

sudo docker compose up -d --build
Enter fullscreen mode Exit fullscreen mode

For windows users:

docker-compose up -d --build 
Enter fullscreen mode Exit fullscreen mode

That’s all! I apologize for any mistake I made. If you find any mistake, please let me know.
I hope it’s helpful

Top comments (0)