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

3

15

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

Marlysmarmaduke answered 31/10, 2019 at 14:40 Comment(2)
Is your host Mac, Windows or Linux? I have a setup that works well on Mac but watch does not work on Windows.Serinaserine
@AdamMendoza Its a MacMarlysmarmaduke
S
39

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",
    
Sardius answered 28/1, 2020 at 3:51 Comment(3)
For ts-node-dev the --poll did the trick. This is not on their readme, but in the source code, it does appear.Helli
ts-node-dev --poll worked for meInextensible
this should be addressed in ts-node-dev's docsZoonosis
T
5

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.

Through answered 6/1, 2021 at 11:41 Comment(0)
P
0

Cleaning up all volumes/images/containers and rebuilding them did it for me.

#!/bin/bash

echo "Cleaning"
docker-compose stop
docker-compose rm
sudo docker-compose down -v
docker volume ls
docker volume prune
docker image prune
docker ps

to rebuild docker-compose up --build

Peta answered 15/2, 2023 at 18:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.