Passer au contenu principal

🐳 Qu'est-ce que Docker ?

📖 Définition

Docker est une plateforme qui exécute des applications dans des environnements isolés appelés conteneurs. Les conteneurs regroupent une application avec toutes ses dépendances, garantissant qu'elle s'exécute de manière identique partout. Il résout le problème "ça marche sur ma machine..." et rend le développement, les tests et le déploiement simples et cohérents.

🎯 Comprendre par les Analogies

Conteneurs de Transport

Pensez à Docker comme des conteneurs de transport en logistique :

Transport Traditionnel (VM)
├─ Emballage différent pour chaque article
├─ Tailles/poids variés
├─ Méthodes de transport différentes
└─ Inefficace, complexe

Transport par Conteneur (Docker)
├─ Conteneurs standardisés
├─ Peut contenir n'importe quelle marchandise
├─ Compatible bateau, camion, train
└─ Efficace, simple

Conteneur Docker = Package logiciel standardisé

Appartements vs Maisons

Machine Virtuelle (VM) = Maison Individuelle
├─ Infrastructure complète pour chaque maison
├─ Terrain, bâtiment, services tous séparés
├─ Coûteux
└─ Démarrage lent

Conteneur Docker = Appartement
├─ Infrastructure partagée (terrain, bâtiment)
├─ Chaque unité indépendante
├─ Efficace
└─ Emménagement rapide

⚙️ Comment ça Marche

1. Architecture Docker

┌─────────────────────────────────────┐
│ Client Docker (CLI) │
│ docker run, docker build, etc. │
└───────────────┬─────────────────────┘
│ Appels API
┌───────────────▼─────────────────────┐
│ Daemon Docker │
│ Gestion des Conteneurs/Images │
└───────────────┬─────────────────────┘

┌───────────────▼─────────────────────┐
│ Conteneurs (Apps en Exécution) │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │App 1│ │App 2│ │App 3│ │
│ └─────┘ └─────┘ └─────┘ │
└─────────────────────────────────────┘

┌───────────────▼─────────────────────┐
│ OS Hôte (Noyau Linux) │
└─────────────────────────────────────┘

2. Image vs Conteneur

Image = Plan, Classe
├─ Lecture seule
├─ Structure en couches
├─ Réutilisable
└─ Exemple : ubuntu, node, nginx

Conteneur = Instance en Exécution, Objet
├─ Créé à partir de l'image
├─ Exécutable
├─ Environnement isolé
└─ Plusieurs instances possibles

Relation :
Image → Conteneur 1
→ Conteneur 2
→ Conteneur 3

3. Dockerfile → Image → Conteneur

1. Écrire le Dockerfile (Recette)
├─ FROM node:18
├─ COPY package.json .
├─ RUN npm install
└─ CMD ["npm", "start"]

2. Construire l'Image (Cuisine)
docker build -t mon-app .

3. Exécuter le Conteneur (Service)
docker run -p 3000:3000 mon-app

💡 Exemples Pratiques

Écrire un Dockerfile

# Dockerfile d'Application Node.js

# Image de base
FROM node:18-alpine

# Définir le répertoire de travail
WORKDIR /app

# Copier package.json
COPY package*.json ./

# Installer les dépendances
RUN npm ci --only=production

# Copier le code source
COPY . .

# Exposer le port
EXPOSE 3000

# Variables d'environnement
ENV NODE_ENV=production

# Commande à exécuter au démarrage du conteneur
CMD ["node", "server.js"]

Construire et Exécuter des Images

# 1. Construire l'image
docker build -t mon-app-node:1.0 .
# -t : tag (nom:version)
# . : utiliser le Dockerfile dans le répertoire actuel

# 2. Vérifier les images
docker images
# REPOSITORY TAG IMAGE ID CREATED
# mon-app-node 1.0 abc123 il y a 2 minutes

# 3. Exécuter le conteneur
docker run -d \
--name mon-app \
-p 3000:3000 \
-e NODE_ENV=production \
mon-app-node:1.0

# -d : exécuter en arrière-plan
# --name : nom du conteneur
# -p : mappage de port (hôte:conteneur)
# -e : variable d'environnement

# 4. Vérifier les conteneurs en cours d'exécution
docker ps

# 5. Voir les logs
docker logs mon-app

# 6. Accéder au shell du conteneur
docker exec -it mon-app sh

# 7. Arrêter le conteneur
docker stop mon-app

# 8. Supprimer le conteneur
docker rm mon-app

# 9. Supprimer l'image
docker rmi mon-app-node:1.0

Docker Compose (Gérer Plusieurs Conteneurs)

# docker-compose.yml

version: '3.8'

services:
# Application web
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=database
depends_on:
- database
- redis
volumes:
- ./logs:/app/logs

# Base de données
database:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=secret
- MYSQL_DATABASE=monapp
volumes:
- db-data:/var/lib/mysql
ports:
- "3306:3306"

# Cache
redis:
image: redis:7-alpine
ports:
- "6379:6379"

# Nginx (Proxy Inverse)
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- web

volumes:
db-data:
# Commandes Docker Compose

# Démarrer tous les services
docker-compose up -d

# Voir les logs
docker-compose logs -f web

# Redémarrer un service spécifique
docker-compose restart web

# Mettre à l'échelle un service
docker-compose up -d --scale web=3

# Arrêter et supprimer tous les services
docker-compose down

# Supprimer avec les volumes
docker-compose down -v

Exemple Réel : React + Node.js + MongoDB

# frontend/Dockerfile
FROM node:18-alpine AS build

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Servir les fichiers statiques avec Nginx
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# backend/Dockerfile
FROM node:18-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .

EXPOSE 5000
CMD ["node", "server.js"]
# docker-compose.yml
version: '3.8'

services:
frontend:
build:
context: ./frontend
ports:
- "80:80"
depends_on:
- backend

backend:
build:
context: ./backend
ports:
- "5000:5000"
environment:
- MONGO_URL=mongodb://mongodb:27017/monapp
depends_on:
- mongodb

mongodb:
image: mongo:6
volumes:
- mongo-data:/data/db
ports:
- "27017:27017"

volumes:
mongo-data:

Gestion des Volumes de Données

# Créer un volume
docker volume create mes-donnees

# Lister les volumes
docker volume ls

# Monter un volume dans un conteneur
docker run -v mes-donnees:/app/data mon-app

# Monter un répertoire hôte (utile pour le développement)
docker run -v $(pwd):/app mon-app

# Montage en lecture seule
docker run -v $(pwd):/app:ro mon-app

# Supprimer un volume
docker volume rm mes-donnees

# Supprimer tous les volumes inutilisés
docker volume prune

Fichier .dockerignore

# .dockerignore

# Git
.git
.gitignore

# Node
node_modules
npm-debug.log

# Environnement
.env
.env.local

# Sortie de build
dist
build

# IDE
.vscode
.idea

# Tests
coverage
*.test.js

# Documentation
README.md
docs/

🤔 Questions Fréquentes

Q1. Docker vs Machine Virtuelle ?

R :

Machine Virtuelle (VM)
┌─────────────────┐ ┌─────────────────┐
│ App A │ │ App B │
│ Libs │ │ Libs │
│ OS Invité │ │ OS Invité │
│ (Linux) │ │ (Ubuntu) │
└─────────────────┘ └─────────────────┘
┌─────────────────────────────────────┐
│ Hyperviseur (VMware, etc.) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ OS Hôte │
└─────────────────────────────────────┘

Conteneur Docker
┌───────┐ ┌───────┐ ┌───────┐
│ App A │ │ App B │ │ App C │
│ Libs │ │ Libs │ │ Libs │
└───────┘ └───────┘ └───────┘
┌─────────────────────────────┐
│ Moteur Docker │
└─────────────────────────────┘
┌─────────────────────────────┐
│ OS Hôte (Noyau Linux) │
└─────────────────────────────┘

Comparaison :
VM Docker
Taille GB MB
Démarrage Minutes Secondes
Isolation Complète Niveau processus
Performance Surcharge élevée Quasi-natif
Portabilité Faible Élevée

Q2. Qu'est-ce que les Couches d'Image Docker ?

R :

FROM node:18          # Couche 1 : Image de base
WORKDIR /app # Couche 2 : Répertoire de travail
COPY package.json . # Couche 3 : package.json
RUN npm install # Couche 4 : Installer les dépendances
COPY . . # Couche 5 : Code source
CMD ["node", "app.js"]# Couche 6 : Commande de démarrage

# Mise en cache des couches
# - Les couches inchangées sont réutilisées
# - Builds plus rapides

# ✅ Bon : Éléments fréquemment modifiés en dernier
COPY package.json .
RUN npm install # Mis en cache (si package.json inchangé)
COPY . . # Seulement les changements de code

# ❌ Mauvais : Éléments fréquemment modifiés en premier
COPY . . # Changements de code à chaque fois
RUN npm install # npm install s'exécute à nouveau !

Q3. Qu'est-ce que l'Orchestration de Conteneurs ?

R :

Serveur Unique
┌─────────────────────┐
│ ┌───┐ ┌───┐ ┌───┐ │
│ │C1 │ │C2 │ │C3 │ │
│ └───┘ └───┘ └───┘ │
└─────────────────────┘

Orchestration (Kubernetes)
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Server1 │ │ Server2 │ │ Server3 │
│ ┌───┐ │ │ ┌───┐ │ │ ┌───┐ │
│ │C1 │ │ │ │C2 │ │ │ │C3 │ │
│ └───┘ │ │ └───┘ │ │ └───┘ │
└─────────┘ └─────────┘ └─────────┘

Fonctionnalités :
- Déploiement automatisé
- Mise à l'échelle (augmentation/réduction automatique)
- Équilibrage de charge
- Auto-réparation (redémarrer les conteneurs morts)
- Mises à jour progressives

Outils :
- Kubernetes (le plus populaire)
- Docker Swarm
- Amazon ECS

Q4. Utiliser Docker en Développement ?

R :

# Scénario : Environnements différents par membre de l'équipe

# Membre A : macOS, Node 16
# Membre B : Windows, Node 18
# Membre C : Linux, Node 14

# Problème : "Ça marche sur ma machine..."

# Solution : Unifier l'environnement avec Docker

# docker-compose.yml
version: '3.8'
services:
app:
image: node:18
volumes:
- .:/app
working_dir: /app
command: npm run dev
ports:
- "3000:3000"

# Tous les membres de l'équipe utilisent le même environnement
docker-compose up

# Avantages :
# 1. Pas besoin d'installation de Node.js
# 2. Version unifiée
# 3. Dépendances isolées
# 4. Configuration d'environnement partagée

Q5. Sécurité Docker ?

R :

# ✅ Meilleures Pratiques de Sécurité

# 1. Image de base à privilèges minimaux
FROM node:18-alpine # ✅ Petite et sécurisée
FROM node:18 # ❌ Outils inutiles

# 2. Exécuter en tant qu'utilisateur non-root
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs # ✅ Minimiser les privilèges

# 3. Exclure les informations sensibles
# Ajouter à .dockerignore
.env
*.key
secrets/

# 4. Build multi-étapes (supprimer les outils inutiles)
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm run build

FROM node:18-alpine # Image plus petite
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/main.js"]

# 5. Scanner les images
docker scan mon-image

# 6. Système de fichiers racine en lecture seule
docker run --read-only mon-app

# 7. Limites de ressources
docker run --memory="512m" --cpus="1" mon-app

🎓 Prochaines Étapes

Après avoir compris Docker, explorez :

  1. Qu'est-ce que Git ? (À venir) - Contrôle de version et déploiement
  2. Qu'est-ce que Node.js ? (À venir) - Déployer des applications Node avec Docker
  3. Qu'est-ce que le TDD ? - Exécuter des tests dans Docker

Essayez-le Vous-même

# 1. Vérifier l'installation de Docker
docker --version

# 2. Hello World
docker run hello-world

# 3. Exécuter Nginx
docker run -d -p 8080:80 nginx
# Visitez http://localhost:8080

# 4. Vérifier les conteneurs
docker ps

# 5. Arrêter et supprimer
docker stop <container-id>
docker rm <container-id>

# 6. Conteneuriser votre application
# - Écrire le Dockerfile
# - docker build
# - docker run

Commandes Utiles

# Gestion des images
docker pull nginx # Télécharger une image
docker images # Lister les images
docker rmi nginx # Supprimer une image

# Gestion des conteneurs
docker run # Exécuter un conteneur
docker ps # Conteneurs en cours d'exécution
docker ps -a # Tous les conteneurs
docker stop <id> # Arrêter un conteneur
docker start <id> # Démarrer un conteneur
docker restart <id> # Redémarrer un conteneur
docker rm <id> # Supprimer un conteneur

# Logs et débogage
docker logs <id> # Voir les logs
docker logs -f <id> # Suivre les logs
docker exec -it <id> sh # Accéder au shell du conteneur
docker inspect <id> # Informations détaillées

# Nettoyage
docker system prune # Supprimer les ressources inutilisées
docker system prune -a # Supprimer toutes les ressources inutilisées
docker volume prune # Supprimer les volumes inutilisés

🎬 Conclusion

Docker est un outil essentiel pour le développement moderne :

  • Conteneurs : Environnements d'exécution isolés
  • Images : Packages d'applications
  • Portabilité : S'exécute de manière identique partout
  • Efficacité : Léger et rapide

Résolvez les problèmes "ça marche sur ma machine" avec Docker ! 🐳✨