Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot get nodemon/ts-node-dev working on dockerized mean stack

Brand new to the Mean Stack but have managed to get one set up in a dockerized environment by following various tutorials. I mainly used the one explained at https://itnext.io/building-restful-web-apis-with-node-js-express-mongodb-and-typescript-part-1-2-195bdaf129cf

The issue I am having is that to get changes to TypeScript files automatically compiled and serice restarted is failing and I'm unsure what I'm missing in the config. I've tried various iterations using nodemon and ts-node-dev without success.

The server starts up and serves pages 100% but a code change isn't triggering anything.

Below are the Dockerfile (for the Node Express server), package.json and my tsconfig.json, if anyone can possible indicate where I'm going wrong it would be a great help. I've also shown my docker-compose.yml file for the entire stack.

Dockerfile

FROM node:latest

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
RUN npm install --save body-parser express mongoose
RUN npm install --save nocache
RUN npm install --save nodemon typescript ts-node ts-node-dev
RUN npm install --save-dev tsc-watch

# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 3000 27017

# Also tried starting with 'dev'
CMD [ "npm", "run", "prod" ]

package.json

{
  "name": "apis-project",
  "version": "1.0.0",
  "description": "https://itnext.io/building-restful-web-apis-with-node-js-express-mongodb-and-typescript-part-1-2-195bdaf129cf",
  "main": "index.js",
  "scripts": {
    "build": "tsc",
    "dev": "ts-node ./lib/server.ts",
    "start": "nodemon ./dist/server.js",
    "prod": "npm run build && npm run start"
  },
  "keywords": [
    "nodejs",
    "typescript"
  ],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@types/express": "^4.17.1",
    "body-parser": "^1.19.0",
    "express": "^4.17.1",
    "mongoose": "^5.7.7",
    "nodemon": "^1.19.4"
  },
  "devDependencies": {
    "ts-node-dev": "^1.0.0-pre.43"
  }
}


Other variations I've tried within the scripts section are:

    "dev2": "ts-node-dev --respawn --transpileOnly ./lib/server.ts",
    "dev3": "nodemon --watch 'lib/*.ts' --exec 'ts-node' lib/server.ts",
    "dev5": "tsc-watch ./lib/server.ts --outDir ./dist --onSuccess \"node ./dist/server.js\" --onFailure \"echo Beep! Compilation Failed\" --compiler typescript/bin/tsc",
    "dev6": "tsc-watch ./lib/*.ts --outDir ./dist --onSuccess \"node ./dist/server.js\" --onFailure \"echo Beep! Compilation Failed\" --compiler typescript/bin/tsc",
    "dev7": "tsc-watch ./lib/server.ts --outDir ./dist --onSuccess \"node ./dist/server.js\" --onFailure \"echo Beep! Compilation Failed\" --compiler typescript/bin/tsc",
    "x-compile": "tsc && node ./dist/server.js",
    "x-dev": "./node_modules/nodemon/bin/nodemon.js -e ts  --exec \"npm run x-compile\"",

tsconfig.json

// tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "moduleResolution": "node",
        "pretty": true,
        "sourceMap": true,
        "target": "es6",
        "outDir": "./dist",
        "baseUrl": "./lib"
    },
    "include": [
        "lib/**/*.ts"
    ],
    "exclude": [
        "node_modules"
    ]
}

docker-compose.yml

version: '3' # specify docker-compose version

# Define the services/containers to be run
services:
#  angular: # name of the first service
#    hostname: localhost
#    build: serviceangular # specify the directory of the Dockerfile
#    ports:
#      - 4200:4200 # specify port forewarding
#

  express: #name of the second service
    build: ./node-apis-project # specify the directory of the Dockerfile
    ports:
      - 3000:3000 #specify ports forwarding
    links:
      - database

  database: # name of the third service
    image: mongo # specify image to build container from
    ports:
      - 27017:27017 # specify port forewarding
    volumes:
      - ./data/mongo:/data/db

volumes:
  data:
    external: true

Docker logs output when viewing the express container

> [email protected] prod /usr/src/app
> npm run build && npm run start


> [email protected] build /usr/src/app
> tsc


> [email protected] start /usr/src/app
> nodemon ./dist/server.js

[nodemon] 1.19.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): lib/**/*
[nodemon] watching extensions: js
[nodemon] starting `node ./dist/server.js`
(node:62) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
(node:62) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
Express server listening on port 3000

like image 304
John Cogan Avatar asked Oct 31 '19 14:10

John Cogan


2 Answers

You might have found a solution by now. I'll leave this answer as a reference.

  1. In docker-compose.yml, ensure that you already mapped the source code to the app service. In your case:

    version: '3'
    
    services:
      ...
      express:
        build: ./node-apis-project
        ports:
          - 3000:3000
        links:
          - database
        volumes:
          - .:/usr/src/app # same as WORKDIR in your Dockerfile
      ...
    
  2. According to nodemon manual, normal watch mechanism might fail in some networked environments (such as a container running nodemon reading across a mounted drive) so you might have to use polling which is a little CPU intensive (6-10% CPU utilization in my case)

    For nodemon, use --legacy-watch:

        "dev3": "nodemon --legacy-watch --watch 'lib/*.ts' --exec 'ts-node' lib/server.ts",
    

    For ts-node-dev, use --poll:

        "dev2": "ts-node-dev --poll --respawn --transpile-only ./lib/server.ts",
    
like image 112
weeix Avatar answered Sep 17 '22 20:09

weeix


For anyone else that landed on this issue due to issues with Kubernetes + ts-node-dev failing and sending errors similar to :

[INFO] 09:29:47 ts-node-dev ver. 1.1.1 (using ts-node ver. 9.1.1, typescript ver. 4.1.3)
 
npm ERR! path /app
 
npm ERR! command failed
 
npm ERR! signal SIGKILL
 
npm ERR! command sh -c ts-node-dev src/index.ts

check the resources you have allocated to the container in your deployment yaml and try de-restricting them.

this resolved the issue for me and I was able to tune in to the resources following this.

like image 20
Kingswell Avatar answered Sep 18 '22 20:09

Kingswell