Setup Lab Guide

Setup Project 4: TypeScript/Node/Express & Docker Backend Scaffold

Deploy a robust, compiled TypeScript HTTP server wrapper inside a secure multi-stage Docker container.
Environment
NodeJS / Express / Docker / VM
Difficulty
⭐⭐☆☆☆ (Moderate)
Course Module
IoT Web Development
Deliverables
Node ts index file, Docker configs
1. Docker Multi-Stage Containerization Architecture

Standard Node deployments copy devDependencies (like TypeScript compilers) directly into production containers, leading to bloated, insecure images. The diagram below details a multi-stage Docker build pipeline. Stage 1 (Builder) installs all modules and compiles the TypeScript code into vanilla JavaScript. Stage 2 (Runner) copies only the compiled JS and installs production dependencies, minimizing the final image size and reducing security risks.

STAGE 1: BUILD ENVIRONMENT Base Image: node:20-alpine npm install (Including DevDeps) Compilation: npx tsc Transpiles src/*.ts to dist/*.js Image Size: ~450MB Contains TSC Compiler & Types STAGE 2: PRODUCTION RUNTIME Copy: dist/*.js only Discards original TS source files Base Image: node:20-alpine npm install --only=production Image Size: ~80MB No compilers or source maps
2. Part 1: Step-by-Step Backend Project Initialization & Commands

Follow these detailed steps to build the TypeScript backend scaffold, configure your tsconfig file, write the server code, and containerize the environment.

STEP 1

Launch VM Terminal and Create Backend Workspace

Boot up your VirtualBox Ubuntu machine. Open the terminal (Ctrl+Alt+T) and create a directory to organize your backend files.

ubuntu@iot-vm:~$ mkdir -p ~/workspace/backend_scaffold && cd ~/workspace/backend_scaffold
We run `mkdir -p` and `cd` to generate and enter a dedicated workspace directory named `~/workspace/backend_scaffold` to isolate our backend scaffold configuration files.
STEP 2

Initialize Node.js Project

Create a package configuration file using default settings.

ubuntu@iot-vm:~/workspace/backend_scaffold$ npm init -y
We run `npm init -y` to generate a default package configuration file (`package.json`), which we will use to manage dependencies and build scripts.
STEP 3

Install TypeScript and Express Dependencies

Install the required packages to build and compile the Express server.

ubuntu@iot-vm:~/workspace/backend_scaffold$ npm install express && npm install -D typescript @types/node @types/express ts-node
We install the runtime dependency `express` along with the development dependencies `typescript`, `ts-node`, and type definition files to compile and run the backend.
STEP 4

Generate TypeScript Compiler Configuration File

Initialize the default tsconfig file, which defines the compiler settings.

ubuntu@iot-vm:~/workspace/backend_scaffold$ npx tsc --init
We run `tsc --init` to generate a default TypeScript compiler configuration file (`tsconfig.json`), which we will configure to output build artifacts to a dedicated directory.
STEP 5

Configure Compiler Directories in tsconfig.json

Open `tsconfig.json` and configure the output and source root directories.

Settings to update (gedit tsconfig.json): 1. Locate line '"target": "es2016"'. Verify it is active. 2. Locate and uncomment '"outDir": "./dist"'. This defines the target directory for compiled JS code. 3. Locate and uncomment '"rootDir": "./src"'. This defines the directory containing your source code. 4. Save and exit the editor.
We configure output and root directories in `tsconfig.json` to instruct the compiler to output compiled JS files to `/dist` and compile source files from `/src`.
STEP 6

Create the Server Entry File

Open the graphical text editor in a background thread to write the Express server code.

ubuntu@iot-vm:~/workspace/backend_scaffold$ mkdir src && gedit src/index.ts &
We create the `/src` directory and launch the graphical editor in a background thread to write the TypeScript entry file.
STEP 7

Create the Multi-Stage Dockerfile

Open a new file in gedit to write the multi-stage Docker build configuration.

ubuntu@iot-vm:~/workspace/backend_scaffold$ gedit Dockerfile &
We create `Dockerfile` in the root directory to define the build and runtime stages for the container.
STEP 8

Create the Docker Compose Configuration File

Open a new file in gedit to configure the Docker Compose service routing rules.

ubuntu@iot-vm:~/workspace/backend_scaffold$ gedit docker-compose.yml &
We create `docker-compose.yml` to define port forwarding rules and environment variables for the service.
STEP 9

Build and Launch the Containerized Service

Build and start the containerized service using Docker Compose. The terminal will output compilation logs as the container starts.

ubuntu@iot-vm:~/workspace/backend_scaffold$ sudo docker-compose up --build
We run `docker-compose up --build` as root to build the container images and launch the services defined in the compose file.
3. Web Service Port Forwarding Model

The diagram below illustrates the port forwarding paths, mapping incoming requests from the host OS browser to the containerized Express backend.

Windows Host Browser http://localhost:3000 Targets Port 3000 VirtualBox VM NAT Maps Host Port 3000 To VM Interface Port 3000 Docker Container Express Server Listens on Port 3000
4. Part 2: Complete Codebases & Container Configurations

Below is the complete C++ firmware code showing how abstract inheritance interfaces work, followed by the complete Python script to listen to the serial port and print the data.

Asset 1: TypeScript Express Server File (`src/index.ts`)

Line-by-Line Code Breakdown

// Setup Project 4: TypeScript Express Entry Server File import express, { Request, Response } from 'express'; const app = express(); const PORT = process.env.PORT || 3000; app.use(express.json()); // Health Check Endpoint app.get('/health', (req: Request, res: Response) => { res.status(200).json({ status: 'online', timestamp: new Date().toISOString() }); }); app.listen(PORT, () => { console.log(f"Server successfully running inside container on port {PORT}."); });

Asset 2: Multi-Stage Docker Build Configuration (`Dockerfile`)

Line-by-Line Code Breakdown

# Multi-Stage Build Dockerfile # Stage 1: Build compilation environment FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npx tsc # Stage 2: Production runtime environment FROM node:20-alpine AS runner WORKDIR /app COPY package*.json ./ RUN npm install --only=production COPY --from=builder /app/dist ./dist EXPOSE 3000 ENV NODE_ENV=production CMD ["node", "dist/index.js"]

Asset 3: Compose Service Orchestration File (`docker-compose.yml`)

Line-by-Line Code Breakdown

# Docker Compose Orchestration Setup version: '3.8' services: web-backend: build: . container_name: iot_node_backend ports: - "3000:3000" environment: - PORT=3000 - NODE_ENV=production restart: always
5. Deliverables Summary

Created Workspace Assets

  • TypeScript entry server: src/index.ts.
  • TypeScript compiler parameters: tsconfig.json.
  • Container blueprints: Dockerfile & docker-compose.yml.

Verification Proof

  • Docker build output showing compilation steps completing without errors.
  • A screenshot of the host web browser loading http://localhost:3000/health, displaying the status response: {"status":"online"}.
6. Closing Explanation: Why We Did This & What It Accomplishes

Architectural Intent & Operational Impact

Why We Did This

What This Accomplishes