Docker et TypeScript : conteneurisation d'applications de A à Z
La conteneurisation est devenue la norme du développement moderne. Docker permet d'empaqueter une application TypeScript avec toutes ses dépendances et son environnement, garantissant son fonctionnement stable sur n'importe quelle plateforme — du poste de travail local du développeur au serveur de production. Dans cet article, nous allons parcourir le cycle complet : du Dockerfile de base à la construction optimisée pour la production.
1. Bases de Docker pour le développeur TypeScript
Docker est une plateforme pour créer, livrer et exécuter des applications dans des environnements isolés (conteneurs). Pour les applications TypeScript, qui sont compilées en JavaScript et fonctionnent sur Node.js, Docker résout trois problèmes clés :
- Reproductibilité de l'environnement : oubliez l'expression "ça marche chez moi". Les versions de Node.js, npm et des paquets système sont figées dans l'image.
- Isolation : chaque application fonctionne dans son propre conteneur, sans affecter les autres services.
- Mise à l'échelle : les conteneurs sont facilement répliqués et orchestrés.
Avant de commencer, assurez-vous d'avoir installé Docker et Docker Compose. Vous pouvez vérifier avec les commandes :
docker --versiondocker-compose --version2. Création d'un Dockerfile pour une application TypeScript
Commençons par une application TypeScript simple. Supposons que nous ayons un fichier src/index.ts :
import express from 'express';
const app = express();const port = process.env.PORT || 3000;
app.get('/', (req, res) => { res.send('Bonjour depuis Docker + TypeScript !');});
app.listen(port, () => { console.log(`Serveur démarré sur le port ${port}`);});Créons maintenant un Dockerfile à la racine du projet :
# ---- Image de base pour le développement ----FROM node:18-alpine AS baseWORKDIR /appCOPY package*.json ./RUN npm ci --only=production
# ---- Compilation TypeScript ----FROM base AS buildCOPY tsconfig.json ./COPY src/ ./src/RUN npm ci && npm run build
# ---- Image de production ----FROM node:18-alpine AS productionWORKDIR /appCOPY --from=build /app/dist ./distCOPY --from=base /app/node_modules ./node_modulesEXPOSE 3000CMD ["node", "dist/index.js"]Il s'agit d'une construction multi-étapes (multi-stage build). Elle permet de :
- Installer toutes les dépendances (y compris les devDependencies) uniquement lors de l'étape de construction
- Ne placer dans l'image finale que le JavaScript compilé et les dépendances de production
- Réduire la taille de l'image de 2 à 3 fois
Construisez l'image et lancez le conteneur :
docker build -t mon-app-typescript .docker run -p 3000:3000 mon-app-typescript3. Configuration de docker-compose pour le développement et la production
Docker Compose simplifie le travail avec les applications multi-conteneurs. Créons un docker-compose.yml :
version: '3.8'
services: app: build: context: . target: development ports: - "3000:3000" volumes: - .:/app - /app/node_modules environment: - NODE_ENV=development command: npm run dev
# Version de production app-prod: build: context: . target: production ports: - "80:3000" environment: - NODE_ENV=productionPour plus de commodité, ajoutons un Dockerfile séparé pour le développement (on peut étendre l'image de base) :
# Dockerfile.devFROM node:18-alpineWORKDIR /appCOPY package*.json ./RUN npm installCOPY . .EXPOSE 3000CMD ["npm", "run", "dev"]Lancement en mode développement :
docker-compose up appGrâce à volumes, les modifications du code sont immédiatement prises en compte (hot-reload), et /app/node_modules est exclu pour ne pas écraser les dépendances du conteneur.