Post

[Nestjs] Setting Up a NestJS Monorepo with Docker

Introduction

In this post, I will introduce how to set up a monorepo in NestJS and configure it with Docker for real-time development.

Let’s begin!


What is Monorepo?

A Monorepo (short for “monolithic repository”) is a single version-controlled repository that holds the code for multiple projects, which may or may not be related to one another. Instead of having separate repositories for each project, a monorepo combines them into one.

Step: 1. Install the NestJS CLI.

1
npm install -g @nestjs/cli

Step: 2. Create a new Monorepo project.

1
2
nest new nestjs-monorepo-docker
cd nestjs-monorepo-docker

Step: 3. Set Up the Monorepo

I will create the admin and user apps, along with the entity and common libraries for shared use.

  • apps/admin: Admin app
  • apps/user: User app
  • libs/common: For shared utilities, interceptors, filters, etc.
  • libs/entity: For shared entity definitions (e.g., when using TypeORM)
  • Use the NestJS CLI to add the admin, user, common, and entity modules.
    1
    2
    3
    4
    
    nest generate app admin
    nest generate app user
    nest generate lib common
    nest generate lib entity
    
  • Final Folder Structure Example:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    nestjs-monorepo-docker
    ├── apps
       ├── admin    
       └── user
    ├── libs
       ├── common
       └── entity
    ├── docker-compose.yml
    ├── package.json
    └── tsconfig.json
    

Step: 4. Remove Unnecessary Folders and Modify nest-cli.json

At this step, there will be a total of three folders inside the apps directory: admin, user, and nestjs-monorepo-docker. You can delete the nestjs-monorepo-docker folder.

  • Modify nest-cli.json

In this file, change the sourceRoot to src and remove any settings related to nestjs-monorepo-docker under projects.

  • Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{
  "$schema": "https://json.schemastore.org/nest-cli",
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "monorepo": true,
  "projects": {
    "admin": {
      "type": "application",
      "root": "apps/admin",
      "entryFile": "main",
      "sourceRoot": "apps/admin/src",
      "compilerOptions": {
        "tsConfigPath": "apps/admin/tsconfig.app.json"
      }
    },
    "user": {
      "type": "application",
      "root": "apps/user",
      "entryFile": "main",
      "sourceRoot": "apps/user/src",
      "compilerOptions": {
        "tsConfigPath": "apps/user/tsconfig.app.json"
      }
    },
    "common": {
      "type": "library",
      "root": "libs/common",
      "entryFile": "index",
      "sourceRoot": "libs/common/src",
      "compilerOptions": {
        "tsConfigPath": "libs/common/tsconfig.lib.json"
      }
    },
    "entity": {
      "type": "library",
      "root": "libs/entity",
      "entryFile": "index",
      "sourceRoot": "libs/entity/src",
      "compilerOptions": {
        "tsConfigPath": "libs/entity/tsconfig.lib.json"
      }
    }
  }
}

Step: 5. Write the Dockerfile and modify the package.json.

  • apps/admin/Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN yarn install

COPY . .

RUN yarn build:admin

CMD ["yarn", "start:admin"]

The user Dockerfile can be set up similarly, but replace admin with user.

  • Add the following scripts to package.json:
1
2
3
4
5
6
"scripts":{
    "start:user": "nest start user --watch",
    "start:admin": "nest start admin --watch",
    "build:user": "nest build user",
    "build:admin": "nest build admin",
  }

Step: 6. Write the docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
services:
  admin:
    build:
      context: .
      dockerfile: apps/admin/Dockerfile
    ports:
      - '3001:3000'
    volumes:
      - .:/app
      - /app/node_modules
    command: yarn start:admin
    depends_on:
      - db

  user:
    build:
      context: .
      dockerfile: apps/user/Dockerfile
    ports:
      - '3000:3000'
    volumes:
      - .:/app
      - /app/node_modules
    command: yarn start:user
    depends_on:
      - db

  db:
    image: postgres:15
    ports:
      - '5432:5432'
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Step: 7. Run Docker Compose

1
docker-compose up --build
  1. Check the Connect PostgreSQL
    • postgresql: http://localhost:5432
  2. Check the NestJS App
    • user: http://localhost:3000
    • admin: http://localhost:3001

Conclusion

Today, I worked on setting up a NestJS project as a monorepo, deploying it to Docker, and configuring it for real-time code builds.

A monorepo structure makes development more convenient by enabling the use of shared modules and a common database, which improves reusability and simplifies code management.

I hope you can use this sample app as a foundation to create your own amazing projects!

Thank you for reading, and happy blogging! 🚀

References

This post is licensed under CC BY 4.0 by the author.