Tips for monitoring changes to files while developing a NestJs application within a Docker container

Having an issue with NestJS and Docker here. Trying to run the development script using npm start: dev, but encountering a problem where the app runs fine but doesn't detect any changes in the source files, hindering the development process.

Here's a snippet from my docker-compose.yml:

messages:
   image: c2c/messages:v1
   command: npm run start:dev
   build:
     context: ./services/c2c-server-messages
     dockerfile: Dockerfile
   container_name: c2c_server_messages
   depends_on:
     - postgres
     - nginx
   networks:
     c2c_net:
       ipv4_address: 172.28.1.5

And the Dockerfile for my Nest app:

FROM node:10-alpine
WORKDIR /api/messages
ADD . .
RUN npm install
EXPOSE 3000
CMD ["npm", "run", "start"]

The npm start:dev script in my package.json:

"start:dev": "tsc-watch -p tsconfig.build.json --onSuccess \"node dist/main.js\"",

While the console output gives me this info, the app fails to pick up on file changes:

c2c_server_messages | 7:26:29 PM - Found 0 errors. Watching for file changes.
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [NestFactory] Starting Nest application...
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [InstanceLoader] TypeOrmModule dependencies initialized +63ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [InstanceLoader] AppModule dependencies initialized +2ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [InstanceLoader] TypeOrmCoreModule dependencies initialized +151ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [InstanceLoader] TypeOrmModule dependencies initialized +1ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [InstanceLoader] MessageModule dependencies initialized +2ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [RoutesResolver] AppController {/}: +8ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [RouterExplorer] Mapped {/, GET} route +6ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [RoutesResolver] MessageController {/messages}: +1ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [RouterExplorer] Mapped {/, POST} route +2ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [RouterExplorer] Mapped {/all, GET} route +2ms
c2c_server_messages | [Nest] 36   - 07/31/2019, 7:26 PM   [NestApplication] Nest application successfully started +5ms

Answer №1

Successfully implemented!

The crucial step is to establish a volume in docker-compose using the root directory of your microservice folder on the local machine. In this scenario, designate ./services/c2c-server-messages as the root path for the app within the container at :/api/messages.

By doing so, you are utilizing your local files to execute the application instead of relying on files copied into the container. This setup enables you to monitor changes when saving a file.

Here's an illustration:

  messages:
   image: c2c/messages:v1
   volumes:
    - ./services/c2c-server-messages:/api/messages
   command: npm run start:dev
   build:
     context: ./services/c2c-server-messages
     dockerfile: Dockerfile
   container_name: c2c_server_messages
   depends_on:
     - postgres
     - nginx
   networks:
     c2c_net:
       ipv4_address: 172.28.1.5

Answer №2

After hours of searching, I finally discovered the solution at this helpful link.

Facing a similar issue, I managed to resolve it by including

"watchOptions": { "watchFile": "fixedPollingInterval" }
in my tsconfig file.

Answer №3

Introducing a new method to accomplish this task. Presenting the

docker compose watch 

feature, which enables you to synchronize files with your service container.

The available actions include:

  • sync
  • rebuild
  • sync+restart

See below for a sample docker compose file:

services:
  web:
    build: .
    command: npm start
    develop:
      watch:
        - action: sync
          path: ./web
          target: /src/web
          ignore:
            - node_modules/
        - action: rebuild
          path: package.json

For more information, visit https://docs.docker.com/compose/file-watch/

Answer №4

When you execute the command docker-compose ..., it will search for a corresponding image (c2c/messages:v1). If the image is found locally, it will run it. If not found, your docker-compose.yaml file will prompt docker-compose to build the image.

  • If the image is located, it will be executed.
  • If the image is not found, the docker-compose.yaml file will instruct docker-compose to build the image.

To make changes to the running process, one method is to modify the files inside the container image and then trigger the process to reload them. However, it is recommended to have 'immutable' containers (containers that do not change).

One approach to handle this situation is:

  • Include your source code in source control.
  • Use a unique identifier of your source code to detect any modifications.

(typically a hash of your source code such as with git git --rev-parse HEAD)

If there are alterations made to your source code, the hash will also change. This can be used to initiate a rebuild of the image when docker-compose restarts. A simple way to achieve this would be:

  • TAG=$(git rev-parse HEAD)
  • Subsequently utilizing the hash as the tag for your image (instead of v1), e.g. c2c/messages:${TAG}

The workflow would then involve:

  • Make changes to your source code.
  • Calculate the hash.
  • docker-compose up... pointing to the image tagged with the hash for a forced rebuild.

By using source control, you maintain a history of your source code.

Employing image tags based on your source code's hashes enables you to associate images with specific commits.

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

The concept of Typescript involves taking a particular type and generating a union type within a generic interface

Picture a straightforward CollectionStore that contains methods for creating and updating a record. The create() method takes in a set of attributes and returns the same set with an added id property. On the other hand, the update method requires the set t ...

What steps are involved in setting up a nginx reverse proxy for a nodejs (express) application with docker-compose configuration?

I am currently in the process of putting together a docker-compose file that includes an nginx server acting as a reverse proxy for a nodejs application. In summary, here is how I envision it: Browser(localhost:8000) -> Nginx(port:80) -> Node(port:3 ...

Learn how to extend components in Typescript and determine necessary arguments. Discover how to apply this knowledge in an Angular use case by extending mat-side-nav

Background: The Angular Material Design component known as mat-side-nav operates in a specific structure for its dynamics: <mat-sidenav-container> <mat-sidenav> </mat-sidenav> <mat-sidenav-content> </mat-sidenav-conten ...

What is the best way to accomplish this using typescript/adonis?

While exploring some code examples on Bitbucket, I came across a sample that demonstrated how to paginate query results using JavaScript. However, as I attempted to apply it in my project, I encountered difficulties in declaring the types required for the ...

Tips for Disabling ML5 Posenet

Looking to halt Posenet after completing app task private sketch(p: any) { p.setup = () => { this.poseNet = ml5.poseNet(p.createCapture(p.VIDEO), { outputStride: 8 }); this.poseNet.on(&apos ...

Angular 2 error: "unknown element" issue persists despite exhausting all attempted solutions

Here's a typical scenario where I attempt to incorporate a component from another module : External component : import { Component, ViewEncapsulation, ElementRef, ViewChild, Input, Output, EventEmitter } from '@angular/core'; declare ...

Ways to verify the identity of a user using an external authentication service

One of my microservices deals with user login and registration. Upon making a request to localhost:8080 with the body { "username": "test", "password":"test"}, I receive an authentication token like this: { "tok ...

Angular's capability for manipulating data asynchronously

I am relatively new to this, and I am facing difficulties in handling data manipulation in the frontend of an app that I'm currently developing. In my code, there are two functions named "getTipoEtapas()" and "getEtapasporTransfo" which utilize two s ...

Encountering an unexpected token error when using Typescript with Next

Currently, this is what I have in my _document.tsx file: import Document, { Html, Head, Main, NextScript } from 'next/document'; class CustomDocument extends Document { return = (): JSX.Element => ( <Html lang="en-US"> ...

There is no index signature that accepts a parameter of type 'string' in the type '{ [key: string]: AbstractControl; }'

I'm currently tackling a challenge in my Angular project where I am creating a custom validator for a reactive form. However, I've encountered an error within the custom validators function that I am constructing. Below you will find the relevan ...

Angular 2: A guide to setting up `--module system --experimentalDecorators` flags in your project

I am encountering an issue while compiling my TypeScript file: app/app.component.ts import {Component} from 'angular2/core'; @Component({ selector: 'my-app', template: '<h1>Messenger</h1>' }) export clas ...

Obtain non-numeric parameters from the URL in Angular 2 by subscribing to

How do I handle subscribing to a non-numeric parameter from a URL? Can the local variable inside my lambda function params => {} only be a number? Here's my code: getRecordDetail() { this.sub = this.activatedRoute.params.subscribe( ...

Strange behavior when working with Typescript decorators and Object.defineProperty

I'm currently working on a project that involves creating a decorator to override a property and define a hidden property. Let's take a look at the following example: function customDecorator() { return (target: any, key: string) => { ...

After upgrading to node version 20 and other dependencies, encountering ERR_REQUIRE_ESM issue

Attempting to update node from version 16 to 20 has led me to also consider upgrading some other libraries simultaneously. Upon trying to start my backend after completing the updates, the following error occurred: % yarn run dev [nodemon] 3.0.1 [nodemon] ...

Best practice for encapsulating property expressions in Angular templates

Repeating expression In my Angular 6 component template, I have the a && (b || c) expression repeated 3 times. I am looking for a way to abstract it instead of duplicating the code. parent.component.html <component [prop1]="1" [prop2]="a ...

Error encountered during the production build of Angular 2. No issues reported during development phase

During development, I can successfully run the code below. However, when I deploy to production, I encounter the following errors: node_modules/@angular/common/src/pipes/async_pipe.d.ts(39,38): error TS2304: Cannot find name 'Promise'. node_modu ...

Guide to converting a string into an undefined type

I've been working on parsing a csv file: let lines = csvData.split(/\r\n|\n/); let headers = lines[0].split(','); for (let i = 1; i < lines.length; i++) { let values = lines[i].split(','); ...

When trying to use global.mongoose in Typescript, a type error is being thrown

I'm attempting to incorporate caching into my database connection file in order to streamline the process for my next.js application and avoid repeating the connection step every time I interact with the database. import mongoose from 'mongoose&a ...

The render properties are not compatible with each other

I am currently using ReactQuill as a component, but I encounter this error when implementing it with Typescript. Do you have any suggestions on how to resolve this issue? The JSX element type 'ReactQuill' is not recognized as a constructor fun ...

How to add unique elements to an array in Angular without any duplicates

I need help with pushing elements into an array and decrementing the count of it without duplicates in angular. Any assistance would be greatly appreciated ...