Deploying TypeScript on Kubernetes: A Basic Practical Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why TypeScript and Kubernetes are the Perfect Pair

Modern web development is unthinkable without two things: static typing and scalable infrastructure. TypeScript provides code reliability at compile time, while Kubernetes (K8s) offers automatic container management, load balancing, and self-healing. In this guide, we will walk through the entire path from a simple TypeScript application to running it in a Kubernetes cluster. You will learn how to package your code into a Docker image, write manifests, and deploy a production-ready service.



Step 1: Preparing a TypeScript Application for Containerization

Before thinking about Kubernetes, you need to ensure your application is ready to run in a container. Let's create a simple Express application in TypeScript. Make sure the project root contains package.json, tsconfig.json, and an entry point src/index.ts.



// src/index.tsimport express, { Request, Response } from 'express';

const app = express();const PORT = process.env.PORT || 3000;

app.get('/health', (_req: Request, res: Response) => { res.json({ status: 'ok', timestamp: new Date().toISOString() });});

app.get('/', (_req: Request, res: Response) => { res.send('Hello from TypeScript on Kubernetes!');});

app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});


An important nuance: in production, we do not use ts-node. Therefore, add a build script to package.json:

"scripts": {  "build": "tsc",  "start": "node dist/index.js"}

After running npm run build, the compiled JavaScript will appear in the dist folder. This is the folder we will copy into the Docker image.



Step 2: Creating a Minimal-Sized Docker Image

For production deployment, image size is critically important. We use a multi-stage build: first compile TypeScript in a container with the full SDK, then copy the result into a lightweight image based on node:18-alpine.



# Dockerfile# Stage 1: BuildFROM node:18-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ci --only=productionCOPY tsconfig.json ./COPY src/ ./src/RUN npm run build

# Stage 2: ProductionFROM node:18-alpineWORKDIR /appCOPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesEXPOSE 3000CMD ["node", "dist/index.js"]


Build the image and test it locally:

docker build -t my-ts-app:latest .docker run -p 3000:3000 my-ts-app:latest

Open http://localhost:3000 — you should see the greeting.



Step 3: Kubernetes Manifests — Deployment and Service

Now let's move our image into the cluster. For this, we need two basic manifests: Deployment (manages replicas and updates) and Service (provides network access).



deployment.yaml

apiVersion: apps/v1kind: Deploymentmetadata:  name: ts-app-deploymentspec:  replicas: 2  selector:    matchLabels:      app: ts-app  template:    metadata:      labels:        app: ts-app    spec:      containers:      - name: ts-app        image: my-ts-app:latest        imagePullPolicy: IfNotPresent        ports:        - containerPort: 3000        env:        - name: PORT          value: "3000"        livenessProbe:          httpGet:            path: /health            port: 3000          initialDelaySeconds: 5          periodSeconds: 10        readinessProbe:          httpGet:            path: /health            port: 3000          initialDelaySeconds: 3          periodSeconds: 5


service.yaml

apiVersion: v1kind: Servicemetadata:  name: ts-app-servicespec:  selector:    app                

Blogs

Book Recommendations