DEV Community

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

Posted on

11

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

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay