Introducción: por qué TypeScript y Kubernetes son la pareja ideal
El desarrollo web moderno es impensable sin dos cosas: tipado estático e infraestructura escalable. TypeScript proporciona fiabilidad del código en tiempo de compilación, y Kubernetes (K8s) ofrece gestión automática de contenedores, balanceo de carga y auto-reparación. En esta guía recorreremos el camino completo desde una aplicación TypeScript simple hasta su ejecución en un clúster de Kubernetes. Aprenderá cómo empaquetar el código en una imagen Docker, escribir manifiestos y desplegar un servicio listo para producción.
Paso 1: Preparación de la aplicación TypeScript para contenerización
Antes de pensar en Kubernetes, debe asegurarse de que su aplicación esté lista para ejecutarse en un contenedor. Crearemos una aplicación Express simple en TypeScript. Asegúrese de que en la raíz del proyecto existan package.json, tsconfig.json y el punto de entrada 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('¡Hola desde TypeScript en Kubernetes!');});
app.listen(PORT, () => { console.log(`Servidor ejecutándose en el puerto ${PORT}`);});Un detalle importante: en producción no usamos ts-node. Por lo tanto, en package.json agregue el script de compilación:
"scripts": { "build": "tsc", "start": "node dist/index.js"}Después de ejecutar npm run build, en la carpeta dist aparecerá el JavaScript compilado. Esta carpeta es la que copiaremos en la imagen Docker.
Paso 2: Creación de la imagen Docker con tamaño mínimo
Para el despliegue en producción, el tamaño de la imagen es críticamente importante. Usamos compilación multi-etapa: primero compilamos TypeScript en un contenedor con el SDK completo, luego copiamos el resultado en una imagen ligera basada en node:18-alpine.
# Dockerfile# Etapa 1: CompilaciónFROM node:18-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ci --only=productionCOPY tsconfig.json ./COPY src/ ./src/RUN npm run build
# Etapa 2: ProducciónFROM node:18-alpineWORKDIR /appCOPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesEXPOSE 3000CMD ["node", "dist/index.js"]Construya la imagen y verifique localmente:
docker build -t my-ts-app:latest .docker run -p 3000:3000 my-ts-app:latestAbra http://localhost:3000 — debería ver el mensaje de bienvenida.
Paso 3: Manifiestos de Kubernetes — Deployment y Service
Ahora trasladaremos nuestra imagen al clúster. Para ello necesitaremos dos manifiestos básicos: Deployment (gestiona réplicas y actualizaciones) y Service (proporciona acceso de red).
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: 5service.yaml
apiVersion: v1kind: Servicemetadata: name: ts-app-servicespec: selector: app