Docker y TypeScript: contenerización avanzada de aplicaciones

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Docker y TypeScript: contenerización avanzada de aplicaciones

\n\n

La contenerización de aplicaciones TypeScript con Docker no es solo empaquetar código en una imagen. A nivel avanzado, es un arte de optimización, seguridad y automatización. En este artículo, analizaremos cómo crear imágenes Docker eficientes para TypeScript, gestionar el entorno e integrar la contenerización en un pipeline de CI/CD. Aprenderá a reducir el tamaño de la imagen entre 5 y 10 veces, acelerar la compilación y mejorar el aislamiento de dependencias.

\n\n

1. Compilación multi-etapa (Multi-stage builds) para TypeScript

\n\n

El problema clásico de las imágenes Docker para TypeScript es incluir en la imagen final todas las herramientas de desarrollo: el compilador de TypeScript, las dependencias de desarrollo y los archivos fuente. Esto genera tamaños enormes (a menudo > 1 GB). La solución es la compilación multi-etapa.

\n\n

La idea es simple: la primera etapa (build) compila TypeScript a JavaScript e instala todas las dependencias. La segunda etapa (production) copia solo el JavaScript listo y las dependencias de producción.

\n\n
# Etapa 1: Compilación\nFROM node:20-alpine AS builder\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci --only=development\nCOPY . .\nRUN npm run build\n\n# Etapa 2: Producción\nFROM node:20-alpine AS production\nWORKDIR /app\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package*.json ./\nRUN npm ci --only=production\nEXPOSE 3000\nCMD ["node", "dist/index.js"]
\n\n

Este enfoque reduce el tamaño de la imagen de ~800 MB a ~150 MB. Observe --only=development y --only=production — son banderas clave para separar las dependencias.

\n\n

2. Optimización del almacenamiento en caché de capas de Docker

\n\n

Cada instrucción en un Dockerfile crea una capa. Docker almacena en caché las capas si no han cambiado. El orden correcto de las instrucciones es fundamental para la velocidad de las compilaciones repetidas.

\n\n

Ejemplo incorrecto (rompe la caché):

\n
FROM node:20-alpine\nWORKDIR /app\nCOPY . .\nRUN npm ci\nRUN npm run build\nCMD ["node", "dist/index.js"]
\n\n

Aquí, cualquier cambio en el código fuente (incluso en README.md) invalida la caché para npm ci y la compilación.

\n\n

Ejemplo correcto (conserva la caché):

\n
FROM node:20-alpine AS builder\nWORKDIR /app\nCOPY package*.json tsconfig.json ./\nRUN npm ci --only=development\nCOPY src ./src\nRUN npm run build
\n\n

¿Por qué funciona? Las dependencias cambian raramente, mientras que el código fuente cambia a menudo. Al copiar package*.json por separado, garantizamos que la capa con npm ci solo se reconstruya cuando estos archivos cambien.

\n\n

3. Trabajo con variables de entorno y secretos

\n\n

Para aplicaciones TypeScript en Node.js, el uso de variables de entorno es un estándar. Sin embargo, en Docker hay matices.

\n\n

Error típico: pasar datos sensibles (claves API, contraseñas) mediante ENV en el Dockerfile. Esto deja los secretos en el historial de capas de la imagen.

\n\n

Enfoque correcto:

\n
    \n
  • Use --env-file al iniciar el contenedor
  • \n
  • Para producción, aplique Docker Secrets (en Swarm) o Kubernetes Secrets
  • \n
  • Para desarrollo local, use un archivo .env con docker-compose
  • \n
\n\n

Ejemplo de docker-compose.yml:

\n
version: '3.8'\nservices:\n  app:\n    build: .\n    ports:\n      - "3000:3000"\n    env_file:\n      - .env.production\n    volumes:\n      - ./logs:/app/logs
\n\n

En el código TypeScript, use la librería dotenv para cargar las variables:

\n
import dotenv from 'dotenv';\nimport { resolve } from 'path';\n\ndotenv.config({ path: resolve(__dirname, '../.env') });\n\nconst config = {\n  port: parseInt(process.env.PORT || '3000', 10),\n  dbUrl: process.env.DATABASE_URL,\n  apiKey: process.env.API_KEY\n};\n\nexport default config;
\n\n

Importante: nunca haga commit de archivos .env reales

Blogs

Book Recommendations