Introdução: por que TypeScript e Kubernetes são a dupla ideal
O desenvolvimento web moderno é impensável sem duas coisas: tipagem estática e infraestrutura escalável. TypeScript oferece confiabilidade do código em tempo de compilação, e Kubernetes (K8s) fornece gerenciamento automático de contêineres, balanceamento de carga e self-healing. Neste guia, percorreremos todo o caminho, desde uma simples aplicação TypeScript até sua execução em um cluster Kubernetes. Você aprenderá como empacotar o código em uma imagem Docker, escrever manifestos e implantar um serviço pronto para produção.
Passo 1: Preparando a aplicação TypeScript para conteinerização
Antes de pensar em Kubernetes, é preciso garantir que sua aplicação esteja pronta para ser executada em um contêiner. Vamos criar uma aplicação Express simples em TypeScript. Certifique-se de que na raiz do projeto existam package.json, tsconfig.json e o ponto 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('Hello from TypeScript on Kubernetes!');});
app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});Um detalhe importante: em produção, não usamos ts-node. Portanto, adicione o script de build no package.json:
"scripts": { "build": "tsc", "start": "node dist/index.js"}Após executar npm run build, a pasta dist conterá o JavaScript compilado. É esta pasta que copiaremos para a imagem Docker.
Passo 2: Criando uma imagem Docker com tamanho mínimo
Para implantação em produção, o tamanho da imagem é crucial. Usaremos uma build multi-estágio: primeiro compilamos o TypeScript em um contêiner com o SDK completo, depois copiamos o resultado para uma imagem leve baseada em 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"]Construa a imagem e teste localmente:
docker build -t my-ts-app:latest .docker run -p 3000:3000 my-ts-app:latestAcesse http://localhost:3000 — você deverá ver a saudação.
Passo 3: Manifestos Kubernetes — Deployment e Service
Agora vamos transferir nossa imagem para o cluster. Para isso, precisaremos de dois manifestos básicos: Deployment (gerencia réplicas e atualizações) e Service (fornece acesso à rede).
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