Maximizing the potential of NestJS apps with Docker

I am working on a NestJS project that consists of multiple apps structured as follows:

my-project:
-- apps;
--- app-one
---- src
---- tsconfig.app.json
--- app-two
---- src
---- tsconfig.app.json
-- libs
-- package.json
-- etc...

Within this project, I have two separate apps: app-one and app-two. My question is how to utilize Docker for deploying either app-one or app-two. Deploying a single app is straightforward - creating a Dockerfile in the directory with package.json and then building/running it. However, I am unsure how to approach deploying nested apps.

Any assistance or guidance on this matter would be greatly appreciated.

Answer №1

In order to have multiple Dockerfiles at the root of your project, you can give them different filenames for organization.

my-project:
-- apps;
--- app-one
---- src
---- tsconfig.app.json
--- app-two
---- src
---- tsconfig.app.json
-- libs
-- package.json
-- Dockerfile.app-one
-- Dockerfile.app-two

To handle these Dockerfiles, you will need to execute custom scripts to build the specified application.

Dockerfile.app-one

FROM node:12.17-alpine as builder

WORKDIR /build
COPY package.json yarn.lock ./
RUN yarn

COPY . .
RUN  yarn build:app-one

EXPOSE 3000

CMD [ "yarn", "start:app-one"]

package.json

"scripts": {
  "build:app-one": "nest build app-one",
  "build:app-two": "nest build app-two",
  "start:app-one": "nest start app-one",
  "start:app-two": "nest start app-two",
}

nest-cli.json

{
  "projects": {
    "app-one": {
      "type": "application",
      "root": "apps/app-one",
      "entryFile": "main",
      "sourceRoot": "apps/app-one/src",
      "compilerOptions": {
        "tsConfigPath": "apps/app-one/tsconfig.app.json",
        "assets": []
      }
    },
    "app-two": {
      "type": "application",
      "root": "apps/app-two",
      "entryFile": "main",
      "sourceRoot": "apps/app-two/src",
      "compilerOptions": {
        "tsConfigPath": "apps/app-two/tsconfig.app.json",
        "assets": []
      }
    },
  }
}

Then, denote the filename in your build/deploy tasks within your CI/CD pipeline.

.gitlab-ci.yml

image: docker:git

services:
  - docker:dind

stages:
  - build

build-app-one:
  stage: build
  script:
    - docker build . -f Dockerfile.app-one

build-app-two:
  stage: build
  script:
    - docker build . -f Dockerfile.app-two

If further information is required, refer to the documentation on NestJS monorepo architecture.

Answer №2

Using a single Dockerfile for all applications is a convenient option.

FROM node:18-alpine As build

ARG APP_NAME

WORKDIR /usr/src/app

COPY --chown=node:node package*.json yarn.lock ./

RUN yarn install --frozen-lockfile

COPY --chown=node:node . .

RUN yarn build $APP_NAME

ENV NODE_ENV production
RUN yarn install --production --frozen-lockfile

USER node

###################
# PRODUCTION
###################

FROM node:18-alpine As production

ARG APP_NAME
ENV NODE_ENV production

WORKDIR /usr/src/app
COPY --chown=node:node --from=build /usr/src/app/node_modules ./node_modules
COPY --chown=node:node --from=build /usr/src/app/dist/apps/${APP_NAME}/* .

USER node

CMD ["node", "main.js"]

To build the Docker image, use the following command:

docker build -t <tag-name> --build-arg APP_NAME=<app-name> .

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Launch a modal by clicking a button located in a separate component using Vue JS

I am dealing with 2 components: TestSearchTool and TestModal. My goal is to display the Modal when a button in the TestSearchTool component is clicked. These two components are siblings in the hierarchy, so I am struggling to pass values between them (even ...

Loading images in advance before webpage loads

Welcome friends! This is my first time asking a question here, so I hope I'm doing it right :) I'm looking to preload 3 images before the webpage fully loads so that they all appear simultaneously. Currently, the images load one after another and ...

Extracting information from a hyperlink without the need to actually click on it

Hello, I have recently started learning JavaScript and I am looking to accomplish a specific task. Currently, I am navigating on A.com/. Within the content of A.com/, there is a link labeled as A.com/B. Upon clicking on the link A.com/B, I can see ...

404 error: API endpoint inexistent despite being present

I am encountering an issue while attempting to retrieve a product by its ID. Interestingly, when I tested this using Postman, everything worked flawlessly without any errors. However, when I tried to fetch the data using Angular, it kept returning a 404 no ...

Tips for designing a pre-selection process

I've been considering the idea of implementing a temporary screen that allows users to choose between different options before proceeding to a specific page. For instance, on the contact page, users would be prompted with a question like "Are you loo ...

Make sure to validate for null values when extracting data using the useSelector hook

Could someone help me with checking for null while destructuring data? const { vehicles: { data: { reminderVehicles }, }, } = useSelector((state) => state); The code snippet above is throwing an error message: Attempting to ...

When a Javascript function marked as async is executed, it will return an object

Async function is returning [object Promise] instead of the desired real value. Interestingly, I can see the value in the console log. It seems like this behavior is expected from the function, but I'm unsure how to fix my code. This code snippet is ...

What steps should I take to incorporate the delete feature as described above?

Click here to access the delete functionality Hello there, I need help implementing a delete function similar to the one provided in the link above. Below is the code snippet for your reference. I am utilizing the map method to extract data from an array ...

Adding data to a JSON object using AngularJS

When attempting to insert an object into a JSON object, I am encountering an issue where it duplicates the JSON object. Here is a breakdown of the scenario: <input type="text" style="width: 40% !important;" placeholder="Nom" class="input-sm" ng-model= ...

Can you please explain the meaning of this statement in JavaScript/Node.js with regards to the importance of the => operator and the async and await keywords being used here?

(1) This snippet of code is used to hash a password, but the syntax may be unclear. Why does it utilize async and await in this manner? And why doesn't the => symbol seem to define a function? const hashPassword = async password => await bcrypt ...

Encountering difficulty locating a module despite following the correct path according to the official NEXT.js documentation

Recently, I delved into the world of next.js and found myself engrossed in chapter 4 of the official documentation titled "Creating Layouts and Pages." In this chapter, I was prompted to create a file named layout.tsx and insert the following code: import ...

The async and await functions do not necessarily wait for one another

I am working with Typescript and have the following code: import sql = require("mssql"); const config: sql.config = {.... } const connect = async() => { return new Promise((resolve, reject) => { new sql.ConnectionPool(config).connect((e ...

Can you explain the contrast between EJS's render() function and renderFile() method?

const express = require('express'); const ejs = require('ejs'); const app = express(); app.engine('ejs', ejs.renderFile); app.get('/', (req, res) => { res.render('index.ejs', { ...

Error message: Node: TypeError - Attempted to access the 'sort' property of an undefined variable while using findOneAndUpdate() within a find() operation

My code snippet is shown below: var MongoClient = require('mongodb').MongoClient; MongoClient.connect('mongodb://localhost:27017/school', function(err, db) { if (err) throw err; db.collection('students').find().toArray( ...

Can you explain the distinction between export/import and provide/inject in Vue3?

Can you explain the difference between export/import and provide/inject in Vue3? // parent const data = provide('data', ref(0)) // child const data = inject('data') // parent export const data = ref(0) // child import { data } from & ...

Tips for iterating through an array of images and displaying them in a React component

I am working on a project in my react app where I have 5 images that I want to cycle through indefinitely. The goal is to create an animation where a light bar appears to be constantly moving. The shifting dot in each image will give the illusion of movem ...

Setting up RTL (Right to Left) functionality in Material UI version 5 - A Step-by-Step Guide

After updating my app to version 5 of Material-UI from version 4, I noticed that the RTL support is no longer functioning. I carefully followed the instructions in the documentation: https://mui.com/guides/right-to-left/ The current outcome is that the ...

Using Jquery to create interactive and dynamic webpage elements

I am struggling with a paragraph containing words in a span that are editable upon clicking. The content needs to be dynamically called, but my current approach is not effective. Can anyone provide a solution or a better way to achieve this? Feel free to ...

Error in Typescript/React: Unable to access the property 'MaxEmailLength' as it is undefined

I am facing an unusual problem with TypeScript. I have two static classes that are mutually referencing each other and causing issues. Class ValidationHelper (single file) import { ValidationErrors } from '../dictionary/ValidationErrors'; ex ...

Enhance the appearance of CodeMirror substrings by applying bold formatting without altering

I am currently utilizing codemirror with primefaces extensions in XML Mode. I need to modify the font style of a specific substring to make it bold. For instance, <User> <Name>Micheal</Name> <Age>25</Age> <Addr ...