ts

How to setup Express JS with Docker, TypeScript, Hot Reload, and Debug

Table of Contents

This project gives you a clean setup for an Express.js server using TypeScript and Docker, with hot-reloading and easy debugging. It ensures everything runs consistently across different environments and platforms.

Requirements

  • Install the latest version of Node.js from here.

  • Verify the installation with:

    node --version
  • Install the latest version of Docker from here.

  • Open Docker Desktop and verify that it's running.

  • Verify that Docker is ready with:

    docker info
  • Install the lastest version of Visual studio code from here


1. Initialize the Project

Create a project directory:

   mkdir myapp && cd myapp

Initialize Node.js:

   npm init -y

2. Install Dependencies

Install Express:

   npm install express

Install Dev Dependencies:

   npm install -D @types/express typescript nodemon ts-node rimraf

3. Configure TypeScript

Initialize TypeScript configuration:

   npx tsc --init

Update tsconfig.json:

   {
     "include": [
       "./src/**/*.ts",
       "./src/**/*.js"
     ],
     "compilerOptions": {
       "baseUrl": ".",
       "outDir": "build",
       "rootDir": "src",
       "target": "es6",
       "module": "commonjs",
       "lib": ["es6"],
       "allowJs": false,
       "strict": true,
       "noImplicitAny": true,
       "esModuleInterop": true,
       "skipLibCheck": true,
       "removeComments": true,
       "resolveJsonModule": true,
       "forceConsistentCasingInFileNames": true,
       "experimentalDecorators": true,
       "emitDecoratorMetadata": true
     },
     "exclude": [
       "node_modules/*"
     ]
   }

4. Setup Express

Create the project structure:

   mkdir src

Create a basic Express server:

  • Inside the src directory create an index.ts file and add the following code.

     import express, { Request, Response } from 'express';
    
     const app = express();
     const PORT = process.env.PORT || 3000;
    
     app.get('/', (req: Request, res: Response) => {
       res.send('Hello from Express and TypeScript!').end();
     });
    
     app.listen(PORT, () => {
       console.log(`Server is running on port ${PORT}`);
     });

5. Set Up Development Environment

Create the development directory:

   mkdir development

5.1 Nodemon Configuration

Create nodemon.json: Create a file nodemon.json inside the development folder and add the following code:

   {
     "verbose": true,
     "restartable": "rs",
     "legacyWatch": true,
     "ignore": [".git", "node_modules", "build", "development"],
     "watch": ["src"],
     "execMap": {
       "ts": "node -r ts-node/register"
     },
     "ext": "ts,js"
   }

5.2 TypeScript Development Config

Create dev.tsconfig.json: Create a file dev.tsconfig.json inside the development folder and add the following code:

   {
     "extends": "../tsconfig",
     "compileOnSave": true,
     "compilerOptions": {
       "sourceMap": true,
       "strictNullChecks": true
     }
   }

5.3 Environment Variables

Create .env: Create a file .env inside the development folder and add the following code:

   # General envs
   APP_NAME=Example
   PORT=80
   PRODUCTION=0
   APP_VERSION=1.0.0

6. Docker Setup

Create the Dockerfile for development: Create a file dev.Dockerfile inside the development folder and add the following code:

   # Stage 1: Build
   FROM node:23

   WORKDIR /home/src/app

   COPY package*.json .

   RUN npm install

   COPY tsconfig.json .
   COPY development/nodemon.json ./development/nodemon.json
   COPY development/dev.tsconfig.json ./development/dev.tsconfig.json

Create Docker Compose for development: Create a file dev.docker-compose.yml inside the development folder and add the following code:

   services:
     server:
       build:
         context: ../
         dockerfile: development/dev.Dockerfile
       container_name: "${APP_NAME}-${APP_VERSION}"
       volumes:
         - ../src:/home/src/app/src
       restart: always
       environment:
         PORT: "80"
       ports:
         - "9229:9229" # Debugger port
         - "${PORT}:80"
       command: npm run startDockerDev

7. Update Scripts in package.json

Replace default scripts:

   {
     "buildDev": "rimraf build && tsc -p development/dev.tsconfig.json",
     "startDev": "rimraf build && tsc -p development/dev.tsconfig.json && nodemon --config development/nodemon.json --inspect src/index.ts",
     "buildAndStartDev": "npm run buildDev && npm run startDev",
     "buildProd": "rimraf build && tsc -p .",
     "startProd": "node build/index.js",
     "buildAndStartProd": "npm run buildProd && npm run startProd",
     "startDockerDev": "nodemon --config development/nodemon.json --inspect=0.0.0.0:9229 src/index.ts"
   }

8. Debugging Setup

  • Create a new directory: .vscode in the root directory

Configure VS Code Debugging: Create a file launch.json inside the .vscode folder and add the following code:

   {
     "version": "0.2.0",
     "configurations": [
       {
         "name": "Debug DOCKER server",
         "type": "node",
         "restart": true,
         "request": "attach",
         "port": 9229,
         "address": "127.0.0.1",
         "remoteRoot": "/home/src/app/src",
         "localRoot": "${workspaceFolder}/src"
       }
     ]
   }

9. Visual Studio Code Tasks

Create VS Code tasks: Create a file tasks.json inside the .vscode folder and add the following code:

  {
    "version": "2.0.0",
    "tasks": [
      {
        "label": "Start DOCKER Development server",
        "type": "shell",
        "command": "docker-compose -f ${workspaceFolder}/development/dev.docker-compose.yml up -d"
      },
      {
        "label": "Stop DOCKER Development server",
        "type": "shell",
        "command": "docker-compose -f ${workspaceFolder}/development/dev.docker-compose.yml down"
      },
      {
        "label": "Build DOCKER Development server",
        "type": "shell",
        "command": "docker-compose -f ${workspaceFolder}/development/dev.docker-compose.yml build"
      },
      {
        "label": "Build DOCKER Development server and start",
        "type": "shell",
        "command": "docker-compose -f ${workspaceFolder}/development/dev.docker-compose.yml up --build -d"
      },
      {
        "label": "DELETE DOCKER CACHE",
        "type": "shell",
        "command": "docker system prune -a -f"
      },
      {
        "label": "Re-build and start DOCKER Development server",
        "type": "shell",
        "command": "docker-compose -f ${workspaceFolder}/development/dev.docker-compose.yml down; docker-compose -f ${workspaceFolder}/development/dev.docker-compose.yml up --build -d"
    }
    ]
}

10. Running the Project

If you made it this far then your project is successfully configured and ready to be tested.

Build and Start:

  • In Visual Studio Code, open terminal/tasks and run the task named: Build DOCKER Development server and start
  • Wait for the docker-compose image to finish building.
  • Visit the server at: http://localhost

11. Repository

  • Clone this repo
    git clone https://github.com/JerryUrena/Setup-Express-JS-with-Docker-TypeScript-Hot-Reload-and-Debug

  • Found an error? Edit this Repository on GitHub

recent posts

Jerry Urena

Agile vs. DevOps

Agile vs. DevOps: Understanding the Key Differences and Synergies In the realm of software development, Agile and DevOps are two buzzwords that have revolutionized the

Read More »

Any Question?

© JerryUrena