← HUB ✦ Dev & DevOps — Conteneurisation ✦

DOCKER

Build. Ship. Run. Anywhere.

C'EST QUOI DOCKER ?
🐳 DÉFINITION — POUR LES DÉBUTANTS

Docker permet d'emballer ton application avec tout son environnement (dépendances, config, OS minimal) dans une boîte portable appelée conteneur. Cette boîte tourne de façon identique sur n'importe quelle machine.

🕹️ ANALOGIE GAMING

Sans Docker, ton programme c'est comme un jeu qui ne marche que sur ta machine — "ça marche chez moi !" Un conteneur Docker c'est comme une cartouche de jeu : elle contient tout le nécessaire pour tourner, peu importe la console. Tu la copies, elle marche partout, à l'identique.

📄 IMAGE

La recette. Un snapshot figé, en lecture seule, qui décrit l'environnement complet.

→ Comme un ISO de jeu. Elle ne tourne pas toute seule.

📦 CONTENEUR

L'instance en cours. C'est une image qu'on a lancée — elle tourne, consomme de la RAM.

→ Comme la partie en cours. Tu peux en lancer plusieurs depuis la même image.

Image ≠ Conteneur. Une image est statique (stockée sur disque). Un conteneur est dynamique (en mémoire, en train de tourner). On crée un conteneur à partir d'une image. On peut créer 10 conteneurs depuis la même image.
Dockerfile
la recette
→
docker build
Image
snapshot
→
docker run
Conteneur
en vie
→
docker stop
Arrêté
sur disque
→
docker rm
Supprimé
disparu
STOP VS RM — LA CONFUSION #1 DES DÉBUTANTS
🚨 COMPRENDRE STOP ET RM

C'est la confusion la plus fréquente chez les débutants Docker. Voici la différence :

docker stop

Éteint le conteneur.

Comme éteindre ton PC — il n'est plus allumé, mais il existe encore. Tu peux le rallumer avec docker start.

docker stop mon_conteneur
# Conteneur éteint mais EXISTE encore
# Visible dans : docker ps -a
docker rm

Supprime le conteneur.

Comme jeter le PC à la poubelle — il n'existe plus du tout. L'image reste, mais ce conteneur précis est parti.

docker rm mon_conteneur
# ⚠️ Doit être arrêté d'abord
docker rm -f mon_conteneur
# Force stop + rm en une commande
Created
docker create
→ docker start →
Running ▶
docker run
→ docker stop →
Stopped ■
existe encore
→ docker rm →
Deleted ✗
disparu
Règle d'or : Pour tout supprimer proprement → docker stop MON_CONT puis docker rm MON_CONT. Ou en une seule commande : docker rm -f MON_CONT.
INSTALLATION
⚙️ INSTALLER DOCKER SUR UBUNTU/DEBIAN
# Méthode rapide — script officiel Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# ⚠️ IMPORTANT — Ajouter ton user au groupe docker
# Sans ça, tu devras taper sudo avant CHAQUE commande docker
sudo usermod -aG docker $USER
newgrp docker      # ou déconnecte / reconnecte ta session

# Vérifier que tout fonctionne
docker --version
docker run hello-world   # si tu vois "Hello from Docker!" → ✅
Le hello-world télécharge une mini image et affiche un message. Si tu le vois, Docker est bien installé et fonctionnel.
GÉRER LES IMAGES
📄 IMAGES — PULL, LIST, DELETE
# Chercher une image sur Docker Hub (hub.docker.com)
docker search ubuntu

# Télécharger une image depuis Docker Hub
docker pull ubuntu             # dernière version (latest)
docker pull ubuntu:22.04       # version précise (recommandé)
docker pull nginx:alpine        # image légère basée Alpine
docker pull python:3.11-slim   # Python allégé

# Lister toutes les images téléchargées en local
docker images
# Affiche : REPOSITORY | TAG | IMAGE ID | CREATED | SIZE

# Supprimer une image
docker rmi ubuntu              # par nom
docker rmi a1b2c3d4e5f6       # par ID

# Supprimer toutes les images non utilisées
docker image prune              # images orphelines seulement
docker image prune -a          # toutes celles non utilisées
Tu ne peux pas supprimer une image si un conteneur l'utilise encore, même s'il est arrêté. Supprime d'abord le conteneur avec docker rm.
CRÉER ET GÉRER DES CONTENEURS
📦 DOCKER RUN — LANCER UN CONTENEUR

docker run = télécharge l'image si absente + crée + démarre le conteneur en une commande.

# Lancer Ubuntu en mode interactif avec un terminal bash
docker run -it ubuntu bash
# -i = garde stdin ouvert (interactif)
# -t = alloue un terminal (TTY)
# → Tu te retrouves DANS le conteneur, comme un SSH

# Lancer en arrière-plan (detached, sans bloquer le terminal)
docker run -d nginx
# → retourne l'ID du conteneur, ton terminal reste libre

# Nommer son conteneur (TOUJOURS le faire !)
docker run --name mon_serveur -d nginx
# → plus facile que de retenir l'ID

# Exposer un port : -p PORT_MACHINE:PORT_CONTENEUR
docker run -p 8080:80 nginx
# → http://localhost:8080 → port 80 du conteneur nginx

# Monter un dossier local dans le conteneur
docker run -v $(pwd):/app -it ubuntu bash
# → ton dossier courant est visible dans /app du conteneur

# Auto-suppression après arrêt (parfait pour les tests)
docker run --rm ubuntu echo "test"
# → se lance, affiche "test", se supprime tout seul

# Tout combiné — cas réel
docker run -d --name web -p 8080:80 -v $(pwd):/usr/share/nginx/html nginx
🎮 GÉRER LES CONTENEURS AU QUOTIDIEN
# ── LISTER ─────────────────────────────────────────────
docker ps           # conteneurs EN COURS seulement
docker ps -a        # TOUS (en cours + arrêtés) ← le plus utile

# ── DÉMARRER / ARRÊTER ─────────────────────────────────
docker start  mon_conteneur   # rallumer un conteneur arrêté
docker stop   mon_conteneur   # éteindre proprement (attend l'arrêt)
docker kill   mon_conteneur   # forcer l'arrêt immédiat (urgent)
docker restart mon_conteneur  # stop + start en une commande

# ── ENTRER DANS UN CONTENEUR EN VIE ────────────────────
docker exec -it mon_conteneur bash
# Ouvre un shell DANS le conteneur pendant qu'il tourne
# → comme faire SSH dans le conteneur
# → si bash n'existe pas (image alpine) : utilise sh
docker exec -it mon_conteneur sh

# Lancer une commande sans ouvrir de shell
docker exec mon_conteneur ls /app

# ── LOGS ET MONITORING ─────────────────────────────────
docker logs mon_conteneur          # voir tous les logs
docker logs -f mon_conteneur       # logs en temps réel (Ctrl+C pour quitter)
docker logs --tail 50 mon_conteneur # 50 dernières lignes seulement
docker stats                         # CPU/RAM de TOUS les conteneurs
docker inspect mon_conteneur        # toutes les infos en JSON

# ── COPIER DES FICHIERS ────────────────────────────────
docker cp mon_conteneur:/app/fichier.txt .   # conteneur → local
docker cp fichier.txt mon_conteneur:/app/    # local → conteneur

# ── SUPPRIMER ──────────────────────────────────────────
docker rm mon_conteneur             # ⚠️ doit être arrêté
docker rm -f mon_conteneur          # force stop + rm
docker rm $(docker ps -aq)          # supprimer TOUS les arrêtés
DOCKERFILE — ÉCRIRE SA PROPRE IMAGE
📋 LES INSTRUCTIONS — EXPLIQUÉES POUR DÉBUTANTS
# Dockerfile — chaque ligne est une instruction
# chaque instruction crée une "couche" (layer) dans l'image

FROM    ubuntu:22.04
# OBLIGATOIRE en 1er — image de base sur laquelle on s'appuie

RUN     apt-get update && apt-get install -y gcc make
# Exécute une commande AU MOMENT DU BUILD (construction de l'image)
# Chaque RUN = une nouvelle couche = met en cache séparément

WORKDIR /app
# Définit le dossier de travail par défaut
# Toutes les commandes suivantes s'exécutent depuis /app

COPY    . /app
# Copie les fichiers locaux VERS l'image
# "." = tout le dossier courant → vers /app dans l'image

ENV     PORT=8080
# Définit une variable d'environnement dans le conteneur

EXPOSE  8080
# Documente que le conteneur écoute sur ce port
# ⚠️ C'est seulement de la documentation — le port n'est pas ouvert
# Il faut quand même -p au docker run pour y accéder

CMD     ["./mon_prog"]
# Commande lancée quand on fait "docker run"
# Peut être écrasée par l'utilisateur : docker run image AUTRE_CMD
CMD vs ENTRYPOINT : CMD définit la commande par défaut — l'utilisateur peut la remplacer (docker run image bash). ENTRYPOINT est fixe, l'utilisateur ne peut pas la changer (seulement lui ajouter des arguments). Pour débuter, utilise CMD.
🏗️ EXEMPLE CONCRET — PROJET C HOLBERTON
# Dockerfile à la racine de ton projet

FROM    ubuntu:22.04

RUN     apt-get update && apt-get install -y \
        gcc \
        make \
        valgrind \
        && rm -rf /var/lib/apt/lists/*
# Le && rm nettoie le cache apt → image plus légère

WORKDIR /project

COPY    . .
# Copie tout le dossier courant vers /project

RUN     gcc -Wall -Werror -Wextra -pedantic main.c -o prog

CMD     ["./prog"]
# Pour construire et tester ce Dockerfile :
docker build -t mon-projet .         # construire l'image
docker run --rm mon-projet             # lancer (se supprime après)
docker run --rm -it mon-projet bash   # entrer dedans pour tester
.DOCKERIGNORE — NE PAS TOUT COPIER
🙈 LE .DOCKERIGNORE — MÊME LOGIQUE QUE .GITIGNORE

Quand tu fais COPY . ., Docker copie tout ton dossier. Le .dockerignore te permet d'exclure les fichiers inutiles ou sensibles pour garder une image légère.

# .dockerignore — à créer à la racine du projet

.git              # historique git inutile dans l'image
.gitignore
*.o               # binaires compilés
*.a
a.out
.env              # variables d'environnement / secrets ⚠️
*.log
node_modules/     # pour les projets Node.js
__pycache__/      # pour les projets Python
README.md
Dockerfile        # pas besoin dans l'image
Un bon .dockerignore peut réduire la taille de ton image de plusieurs centaines de Mo. C'est une bonne pratique à toujours appliquer.
DOCKER BUILD — CONSTRUIRE UNE IMAGE
🔨 BUILD — TOUTES LES OPTIONS UTILES
# Construire depuis le dossier courant (Dockerfile présent)
docker build .

# Construire et nommer/tagger l'image
docker build -t mon-image .
docker build -t mon-image:1.0 .        # avec version
docker build -t mon-image:latest .     # latest = version par défaut

# Reconstruire sans cache (si quelque chose ne se met pas à jour)
docker build --no-cache -t mon-image .

# Voir le détail de chaque étape
docker build --progress=plain -t mon-image .
Le cache Docker : Docker mémorise chaque étape (layer). Si tu rebuildes sans toucher à RUN apt-get install, il ne le refait pas. C'est pour ça que les builds suivants sont rapides. --no-cache force tout à refaire depuis zéro.
VOLUMES — PERSISTER LES DONNÉES
💾 POURQUOI LES VOLUMES ?

Problème : quand tu supprimes un conteneur (docker rm), tout ce qui était dedans disparaît. Les volumes permettent de sauvegarder les données en dehors du conteneur.

# ── BIND MOUNT — utiliser un dossier local (développement) ──

# Ton dossier local ↔ visible dans le conteneur
docker run -v $(pwd):/app -it ubuntu bash
# Modifie un fichier dans /app → modifié sur ta machine aussi !
# Parfait en dev pour ne pas rebuild à chaque changement

# ── VOLUME DOCKER — géré par Docker (production) ────────────

docker volume create mes-donnees          # créer
docker volume ls                             # lister
docker volume rm mes-donnees               # supprimer

# Utiliser le volume dans un conteneur
docker run -v mes-donnees:/data -it ubuntu bash
# Les données dans /data survivent même si le conteneur est supprimé
BIND MOUNT (-v $(pwd):/app)

✅ Parfait en développement — modifie en local, effet immédiat dans le conteneur.

VOLUME DOCKER (-v nom:/data)

✅ Parfait en production — données persistantes gérées par Docker, indépendantes du système.

DOCKER HUB — PARTAGER SES IMAGES
☁️ PUSH SUR DOCKER HUB EN 4 ÉTAPES
1

Créer un compte sur hub.docker.com puis se connecter

docker login
# Entrer son username et mot de passe Docker Hub
2

Tagger l'image avec ton username Docker Hub

docker tag mon-image:1.0 noham/mon-image:1.0
# Format : username/nom-image:version
3

Pusher sur Docker Hub

docker push noham/mon-image:1.0
# L'image est maintenant sur hub.docker.com/r/noham/mon-image
4

N'importe qui peut la télécharger

docker pull noham/mon-image:1.0
docker run noham/mon-image:1.0
DOCKER COMPOSE — PLUSIEURS CONTENEURS
🎼 ORCHESTRER PLUSIEURS CONTENEURS

Au lieu de lancer plusieurs docker run à la main, Docker Compose te permet de tout définir dans un seul fichier docker-compose.yml et de tout lancer en une commande.

# docker-compose.yml — exemple app web + base de données

services:

  web:                        # nom du service (tu choisis)
    build: .                  # construire depuis le Dockerfile local
    ports:
      - "8080:5000"           # port machine:port conteneur
    volumes:
      - ./app:/app            # bind mount pour le dev
    depends_on:
      - db                    # attend que db soit prêt

  db:
    image: postgres:15        # image depuis Docker Hub
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=secret

volumes:
  pgdata:                     # volume nommé pour persister la DB
# Commandes Docker Compose
docker compose up              # lancer tout (bloque le terminal)
docker compose up -d          # lancer en arrière-plan
docker compose up --build    # rebuild les images avant de lancer
docker compose down            # arrêter et supprimer les conteneurs
docker compose down -v       # + supprimer les volumes
docker compose ps              # état des services
docker compose logs -f       # logs de tous les services
docker compose exec web bash # shell dans le service 'web'
NETTOYAGE — LIBÉRER DE L'ESPACE
🧹 NETTOYER DOCKER
# Voir combien d'espace Docker utilise
docker system df

# Nettoyage sélectif
docker container prune    # supprimer conteneurs arrêtés
docker image prune        # supprimer images orphelines
docker image prune -a    # supprimer toutes les images inutilisées
docker volume prune       # supprimer volumes inutilisés

# Nettoyage total — tout d'un coup
docker system prune       # conteneurs + images orphelines + réseaux
docker system prune -a   # + toutes les images non utilisées
docker system prune -a supprime tout ce qui n'est pas en cours d'utilisation. Utile pour libérer de l'espace, mais tu devras re-pull les images dont tu as besoin.
RÉSUMÉ — TOUT EN UN COUP D'ŒIL
🗺️ LA CARTE MENTALE COMPLÈTE
╔══════════════════════════════════════════════════════════════════╗
║  LES CONCEPTS EN UNE PHRASE                                      ║
╚══════════════════════════════════════════════════════════════════╝
# Image     = recette statique (sur disque, lecture seule)
# Conteneur = instance active d'une image (en mémoire, en vie)
# Dockerfile= script qui construit une image (RUN, COPY, CMD...)
# Volume    = stockage persistant lié à un conteneur

╔══════════════════════════════════════════════════════════════════╗
║  STOP ≠ RM  —  NE JAMAIS CONFONDRE                               ║
╚══════════════════════════════════════════════════════════════════╝
# docker stop → éteint le conteneur (toujours récupérable)
# docker rm   → supprime définitivement le conteneur
# docker rmi  → supprime une IMAGE (pas un conteneur)

╔══════════════════════════════════════════════════════════════════╗
║  WORKFLOW TYPE DÉBUTANT                                          ║
╚══════════════════════════════════════════════════════════════════╝
docker pull ubuntu                           # 1. récupérer une image
docker run -it --name test ubuntu bash      # 2. créer + entrer dedans
# [... faire des trucs dans le conteneur ...]
# exit  ← pour sortir du conteneur
docker start test                            # 3. rallumer si besoin
docker exec -it test bash                   # 4. re-entrer dedans
docker stop test                             # 5. éteindre
docker rm test                               # 6. supprimer quand fini

╔══════════════════════════════════════════════════════════════════╗
║  RÈGLES D'OR                                                     ║
╚══════════════════════════════════════════════════════════════════╝
# ✅ Toujours nommer tes conteneurs avec --name
# ✅ Utilise --rm pour les conteneurs de test (nettoyage auto)
# ✅ Ajoute un .dockerignore à chaque projet
# ✅ Préfère ubuntu:22.04 à ubuntu:latest (version stable)
# ✅ Utilise -d pour les serveurs, -it pour les shells
# ❌ Ne jamais stocker de mots de passe dans le Dockerfile
# ❌ Ne pas confondre docker stop (éteindre) et docker rm (supprimer)