Comprendre Docker : conteneurs, images, écosystème et mise en pratique sous Windows
À la fin de ce cours, tu seras capable de :
| Savoir/Faire | Objectif |
|---|---|
| Reproduire | Installer Docker Desktop sous Windows et exécuter des commandes de base |
| Comprendre | Expliquer la différence entre un conteneur Docker et une machine virtuelle |
| Comprendre | Identifier les composants de l'écosystème Docker (image, conteneur, Hub, Compose) |
| Appliquer | Lancer des services courants (serveur web, base de données) via Docker |
| Généraliser | Reconnaître les situations où Docker est la bonne solution |
Tu as peut-être déjà vécu cette situation :
Tu développes une application PHP sur ton PC sous Windows avec XAMPP.
Tu l'envoies à un camarade qui a une version différente de PHP.
Ça ne fonctionne plus. 😤
Ou encore :
L'application tourne parfaitement en développement.
On la déploie sur le serveur de production (Ubuntu).
Surprise : erreur au démarrage. Une bibliothèque manque. Une version ne correspond pas.
Ce problème s'appelle le problème de l'environnement.
Une application ne tourne pas seule : elle dépend d'un système d'exploitation, d'une version de langage (PHP 8.1 vs 8.3), de bibliothèques, de variables d'environnement, de fichiers de configuration...
Docker résout ce problème en encapsulant l'application ET son environnement dans une boîte autonome : le conteneur.
Un conteneur Docker tourne de la même façon sur :
💡 Analogie : Pense à un conteneur Docker comme à un aquarium auto-suffisant. Le poisson (l'application) vit dans son eau (son environnement). Peu importe où tu poses l'aquarium, les conditions intérieures restent identiques.
C'est la question que tout le monde se pose. Docker et VirtualBox permettent tous les deux de faire tourner des environnements isolés, mais leur approche est radicalement différente.

Une VM émule un ordinateur complet :
VirtualBox installe un "hyperviseur" qui fait croire à chaque VM qu'elle possède son propre matériel. Chaque VM est lourde : un Ubuntu dans VirtualBox pèse 2 à 4 Go minimum et consomme 1 à 2 Go de RAM rien que pour démarrer.
Un conteneur ne virtualise pas le matériel. Il partage le noyau (kernel) du système d'exploitation hôte et n'isole que les processus et le système de fichiers.
Résultat :
| Critère | Machine Virtuelle (VirtualBox) | Conteneur Docker |
|---|---|---|
| OS inclus | ✅ Oui, OS complet | ❌ Non, partage le noyau hôte |
| Taille | 2–10 Go | 25 Mo – quelques centaines de Mo |
| Démarrage | 1–5 minutes | < 1 seconde |
| Isolation | Totale (matériel virtualisé) | Processus isolés (moins total) |
| Performances | Réduites (overhead) | Quasi-natives |
| Cas d'usage | OS différent, tests OS, isolation forte | Déploiement d'apps, microservices |
| Portabilité | Moyenne | Excellente |
🧠 Note : Sous Windows, Docker Desktop utilise en arrière-plan une petite VM Linux légère (WSL 2 — Windows Subsystem for Linux) pour faire tourner le moteur Docker. L'utilisateur n'a pas à s'en occuper, c'est transparent.

C'est le cœur du système. Il tourne en arrière-plan sur ta machine (on appelle ça un daemon). Il est responsable de :
Une image est un modèle en lecture seule. Elle contient :
Les images sont construites en couches (layers). Chaque instruction du Dockerfile ajoute une couche. Si deux images partagent la même couche de base (ex: Ubuntu), elle n't est téléchargée qu'une seule fois.
Image Ubuntu 22.04 ← couche de base
└── + PHP 8.3 ← couche ajoutée
└── + ton app PHP ← ta couche

Un conteneur est une instance en cours d'exécution d'une image. C'est la "boîte vivante".
Analogie code : Une image = une classe. Un conteneur = une instance (objet).
Image MySQL → conteneur "db-dev" (base de données de développement)
→ conteneur "db-test" (base de données de test)
→ conteneur "db-prod" (base de données de production)
C'est le fichier texte qui contient la recette pour construire une image personnalisée.
# On part d'une image de base officielle
FROM php:8.3-apache
# On copie nos fichiers dans le conteneur
COPY ./src /var/www/html
# On expose le port 80
EXPOSE 80
Avec la commande docker build, Docker lit ce fichier et crée ton image.
C'est le registre officiel d'images Docker. L'adresse : hub.docker.com
On y trouve :
docker pull nginx → télécharge l'image officielle Nginx depuis Docker Hub.
Quand une application a besoin de plusieurs services qui coopèrent (ex: une app PHP + une base de données MySQL + phpMyAdmin), Docker Compose permet de les définir dans un seul fichier docker-compose.yml et de tout démarrer avec une seule commande.
# docker-compose.yml — exemple simplifié
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
phpmyadmin:
image: phpmyadmin
ports:
- "8080:80"
depends_on:
- db
docker compose up → démarre tous les services définis.
C'est l'application graphique pour Windows et macOS. Elle installe et gère automatiquement :
| Besoin | Solution Docker |
|---|---|
| Base de données MySQL sans l'installer | docker run mysql |
| Serveur Apache/Nginx pour tester | docker run nginx |
| Tester une app sur une version PHP différente | Image php:8.1 vs php:8.3 |
| Environnement identique pour toute l'équipe | docker-compose.yml partagé via Git |
| Isoler des projets qui ont des dépendances conflictuelles | Un conteneur par projet |
Oui, absolument. Docker est utilisé en production par des entreprises comme Netflix, Spotify, Airbnb, et des milliers d'autres.
Quelques chiffres :
| Limite | Explication |
|---|---|
| Stateless par défaut | Les données d'un conteneur disparaissent à sa suppression → utiliser des volumes |
| Sécurité | Un conteneur mal configuré peut devenir un vecteur d'attaque (ne pas lancer les conteneurs en root) |
| Complexité à grande échelle | Des dizaines de conteneurs → nécessite Kubernetes ou Docker Swarm |
| Performance réseau | Une légère latence supplémentaire sur les communications inter-conteneurs |
Docker permet de mieux utiliser les ressources d'un serveur. Là où il fallait auparavant un serveur physique par application (beaucoup de gaspillage CPU/RAM), on peut maintenant en faire tourner des dizaines sur la même machine. Moins de serveurs = moins de consommation électrique = moins d'impact environnemental. C'est l'un des arguments écologiques du Cloud-native.
Ouvre PowerShell en administrateur et exécute :
wsl --install
Redémarre le PC si demandé.
Télécharge l'installeur sur : docker.com/products/docker-desktop
Lance l'installeur et coche "Use WSL 2 instead of Hyper-V".
Ouvre un terminal (PowerShell ou CMD) et tape :
docker --version
docker run hello-world
Si tu vois Hello from Docker!, c'est bon ! 🎉
Une fois lancé, Docker Desktop te propose :
# Télécharger une image depuis Docker Hub
docker pull nginx
# Lister les images locales
docker images
# Supprimer une image
docker rmi nginx
# Lancer un conteneur (télécharge l'image si besoin)
docker run nginx
# Lancer en arrière-plan (-d = detached)
docker run -d nginx
# Lancer avec un nom et un port (hôte:conteneur)
docker run -d --name mon-serveur -p 8080:80 nginx
# Lister les conteneurs actifs
docker ps
# Lister TOUS les conteneurs (actifs + arrêtés)
docker ps -a
# Arrêter un conteneur
docker stop mon-serveur
# Supprimer un conteneur
docker rm mon-serveur
# Arrêter ET supprimer automatiquement (--rm)
docker run --rm -p 8080:80 nginx
# Voir les logs d'un conteneur
docker logs mon-serveur
# Logs en temps réel (suivi)
docker logs -f mon-serveur
# Ouvrir un terminal dans un conteneur actif
docker exec -it mon-serveur bash
# Inspecter les détails d'un conteneur
docker inspect mon-serveur
# Supprimer tous les conteneurs arrêtés
docker container prune
# Supprimer toutes les images inutilisées
docker image prune
# Nettoyage global (images, conteneurs, réseaux non utilisés)
docker system prune
# Démarrer tous les services (en arrière-plan)
docker compose up -d
# Arrêter tous les services
docker compose down
# Voir les logs de tous les services
docker compose logs -f
# Reconstruire les images et redémarrer
docker compose up -d --build
Objectif : Lancer un serveur web Nginx en une commande et y accéder depuis ton navigateur.
Niveau Bloom : Reproduire / Appliquer
Nginx est un serveur web très utilisé en production. Normalement, l'installer sous Windows est compliqué. Avec Docker, c'est une seule commande.
1. Ouvre un terminal PowerShell.
2. Lance le conteneur :
docker run -d --name mon-nginx -p 8080:80 nginx
Décortiquons cette commande :
| Argument | Signification |
|---|---|
run |
Crée et démarre un conteneur |
-d |
En arrière-plan (detached) |
--name mon-nginx |
Donne un nom au conteneur |
-p 8080:80 |
Redirige le port 8080 de ta machine vers le port 80 du conteneur |
nginx |
Le nom de l'image à utiliser (téléchargée depuis Docker Hub) |
3. Ouvre ton navigateur et va sur : http://localhost:8080
Tu devrais voir la page de bienvenue de Nginx ✅
4. Vérifie que le conteneur tourne :
docker ps
5. Lis les logs du serveur :
docker logs mon-nginx
Recharge la page du navigateur et regarde les logs se mettre à jour.
6. Arrête et supprime le conteneur :
docker stop mon-nginx
docker rm mon-nginx
--name ?Objectif : Lancer un serveur MySQL complet via Docker, s'y connecter et créer une base de données.
Niveau Bloom : Appliquer / Comprendre
Tu connais MySQL depuis tes cours. L'installer sur un PC prend du temps et "pollue" le système. Avec Docker, tu lances une instance MySQL propre en quelques secondes, que tu peux supprimer après utilisation.
1. Lance MySQL dans un conteneur :
docker run -d \
--name mon-mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=motdepasse \
-e MYSQL_DATABASE=mabase \
mysql:8.0
Note Windows : Sur PowerShell, remplace les
\par des backticks`pour les retours à la ligne, ou écris tout sur une seule ligne.
Décortiquons les nouveaux arguments :
| Argument | Signification |
|---|---|
-p 3306:3306 |
Expose le port MySQL standard |
-e MYSQL_ROOT_PASSWORD=motdepasse |
Variable d'environnement : mot de passe root |
-e MYSQL_DATABASE=mabase |
Crée automatiquement une base "mabase" au démarrage |
mysql:8.0 |
Image MySQL version 8.0 |
2. Attends quelques secondes que MySQL démarre. Surveille les logs :
docker logs -f mon-mysql
Quand tu vois ready for connections, appuie sur Ctrl+C pour quitter les logs.
3. Connecte-toi à MySQL depuis l'intérieur du conteneur :
docker exec -it mon-mysql mysql -u root -pmotdepasse
Tu es maintenant dans le shell MySQL.
4. Teste quelques commandes :
SHOW DATABASES;
USE mabase;
CREATE TABLE eleves (id INT AUTO_INCREMENT PRIMARY KEY, nom VARCHAR(100));
INSERT INTO eleves (nom) VALUES ('Alice'), ('Bob');
SELECT * FROM eleves;
EXIT;
5. Connecte-toi aussi depuis MySQL Workbench ou HeidiSQL sur ta machine hôte :
127.0.0.13306rootmotdepasse6. Supprime le conteneur :
docker stop mon-mysql
docker rm mon-mysql
Recrée le conteneur et retourne voir la table eleves. Elle a disparu. C'est normal : sans volume, les données ne sont pas persistées.
Pour garder les données, on utilise un volume :
docker run -d \
--name mon-mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=motdepasse \
-v mysql_data:/var/lib/mysql \
mysql:8.0
Le -v mysql_data:/var/lib/mysql crée un volume nommé mysql_data qui survit à la suppression du conteneur.
Objectif : Lancer deux services qui coopèrent (MySQL + phpMyAdmin) avec un seul fichier de configuration.
Niveau Bloom : Appliquer / Généraliser
Dans la vraie vie, les applications ont souvent besoin de plusieurs services. Docker Compose permet de les définir ensemble, de gérer leur démarrage dans l'ordre, et de les faire communiquer sur un réseau interne.
1. Crée un dossier docker-mysql-lab sur ton Bureau.
2. Dans ce dossier, crée un fichier docker-compose.yml :
services:
# Service 1 : la base de données MySQL
db:
image: mysql:8.0
container_name: lab_mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: monprojet
MYSQL_USER: dev
MYSQL_PASSWORD: devpass
volumes:
- mysql_data:/var/lib/mysql
networks:
- lab_network
# Service 2 : phpMyAdmin pour gérer la base via navigateur
phpmyadmin:
image: phpmyadmin:latest
container_name: lab_phpmyadmin
restart: unless-stopped
ports:
- "8080:80"
environment:
PMA_HOST: db # Le nom du service MySQL dans le réseau Docker
PMA_PORT: 3306
depends_on:
- db
networks:
- lab_network
# Déclaration du volume persistant
volumes:
mysql_data:
# Déclaration du réseau interne
networks:
lab_network:
3. Ouvre un terminal dans ce dossier et lance tout :
docker compose up -d
Docker va :
lab_networkmysql_datadepends_on)4. Ouvre http://localhost:8080 dans ton navigateur.
Connecte-toi avec :
dbrootsecret5. Crée une table, insère des données.
6. Arrête les services :
docker compose down
Relance avec docker compose up -d. Tes données sont toujours là grâce au volume.
7. Pour tout supprimer y compris les volumes :
docker compose down -v
8888:80 et relance ┌─────────────────────────────────┐
│ DOCKER HUB │
│ (bibliothèque d'images publiques)│
└──────────────┬──────────────────┘
│ docker pull
┌──────────────▼──────────────────┐
│ IMAGE │
│ (modèle en lecture seule) │
└──────────────┬──────────────────┘
│ docker run
┌────────────────────┼────────────────────┐
│ │ │
┌─────────▼──────┐ ┌─────────▼──────┐ ┌─────────▼──────┐
│ Conteneur 1 │ │ Conteneur 2 │ │ Conteneur 3 │
│ (dev) │ │ (test) │ │ (prod) │
└────────────────┘ └────────────────┘ └────────────────┘
| Commande | Action |
|---|---|
docker pull <image> |
Télécharger une image |
docker run -d -p X:Y <image> |
Lancer un conteneur |
docker ps |
Voir les conteneurs actifs |
docker stop <nom> |
Arrêter un conteneur |
docker rm <nom> |
Supprimer un conteneur |
docker logs <nom> |
Voir les journaux |
docker exec -it <nom> bash |
Entrer dans un conteneur |
docker compose up -d |
Démarrer les services Compose |
docker compose down |
Arrêter les services Compose |
Docker favorise la densification des serveurs : là où il fallait 10 serveurs physiques, on peut héberger 10 applications isolées sur un seul serveur bien dimensionné. Cela réduit la consommation électrique, la production de chaleur et les déchets électroniques. C'est l'un des fondements du mouvement Green IT dans les datacenters modernes.