Docker - Partie 1 : Concepts et Fondamentaux

← Retour aux tutoriels | Partie 2 : Dockerfile et Docker Compose →

Parcours d'apprentissage (novice vers expert)

Objectif: comprendre Docker, lancer des conteneurs simples, puis diagnostiquer et optimiser leur exécution.

Fonctionnement: exécute les commandes dans l'ordre et valide l'état avec docker ps, logs et inspect.

1. Qu'est-ce que Docker ?

Définition

Docker est une plateforme de conteneurisation qui permet d'empaqueter une application et toutes ses dépendances dans un conteneur isolé. Ce conteneur peut être exécuté de manière cohérente sur n'importe quel environnement supportant Docker.

Conteneur vs Machine Virtuelle

Machine Virtuelle (VM)          |  Conteneur Docker
--------------------------------|---------------------------
OS complet (plusieurs Go)       |  Partage le kernel (quelques Mo)
Boot lent (minutes)             |  Démarrage instantané (secondes)
Isolation totale                |  Isolation des processus
Gourmand en ressources          |  Léger et efficace
Hyperviseur requis              |  Docker Engine suffit

Avantages de Docker

2. Architecture Docker

Composants principaux

┌─────────────────────────────────────────────┐
│            Docker Client (CLI)              │  ← Vous tapez les commandes ici
└─────────────────┬───────────────────────────┘
                  │ (API REST)
┌─────────────────▼───────────────────────────┐
│           Docker Daemon (dockerd)           │  ← Moteur Docker
│                                             │
│  ┌─────────────────────────────────────┐   │
│  │         Images Docker               │   │  ← Templates read-only
│  │  • ubuntu:22.04                     │   │
│  │  • nginx:latest                     │   │
│  │  • mysql:8.0                        │   │
│  └─────────────────────────────────────┘   │
│                                             │
│  ┌─────────────────────────────────────┐   │
│  │       Conteneurs en cours           │   │  ← Instances d'images
│  │  • webapp (nginx)                   │   │
│  │  • database (mysql)                 │   │
│  │  • cache (redis)                    │   │
│  └─────────────────────────────────────┘   │
│                                             │
│  ┌─────────────────────────────────────┐   │
│  │    Volumes & Networks               │   │  ← Stockage & Réseau
│  └─────────────────────────────────────┘   │
└─────────────────────────────────────────────┘
                  │
┌─────────────────▼───────────────────────────┐
│         Docker Registry (Hub)               │  ← Dépôt d'images
│         hub.docker.com                      │
└─────────────────────────────────────────────┘

Concepts clés

3. Installation de Docker

Linux (Ubuntu/Debian)

# Désinstaller les anciennes versions
sudo apt-get remove docker docker-engine docker.io containerd runc

# Installer les prérequis
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release

# Ajouter la clé GPG officielle Docker
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# Ajouter le dépôt
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Installer Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Ajouter votre utilisateur au groupe docker (éviter sudo)
sudo usermod -aG docker $USER
newgrp docker

# Vérifier l'installation
docker --version
docker compose version

Windows / macOS

Télécharger et installer Docker Desktop depuis docker.com

4. Commandes Docker de base

Gestion des images

# Rechercher une image sur Docker Hub
docker search nginx

# Télécharger une image
docker pull nginx:latest
docker pull ubuntu:22.04

# Lister les images locales
docker images
docker image ls

# Supprimer une image
docker rmi nginx:latest
docker image rm ubuntu:22.04

# Nettoyer les images non utilisées
docker image prune -a

Gestion des conteneurs

# Créer et démarrer un conteneur
docker run nginx

# Mode détaché (background)
docker run -d nginx

# Avec un nom
docker run -d --name mon-nginx nginx

# Avec mappage de port
docker run -d -p 8080:80 --name web nginx
# Accéder à http://localhost:8080

# Avec variable d'environnement
docker run -d -e MYSQL_ROOT_PASSWORD=secret mysql:8.0

# Avec volume (persistance des données)
docker run -d -v /mon/dossier:/var/www/html nginx

# Mode interactif (terminal)
docker run -it ubuntu:22.04 /bin/bash

# Lister les conteneurs actifs
docker ps

# Lister tous les conteneurs (même arrêtés)
docker ps -a

# Arrêter un conteneur
docker stop mon-nginx

# Démarrer un conteneur arrêté
docker start mon-nginx

# Redémarrer un conteneur
docker restart mon-nginx

# Supprimer un conteneur
docker rm mon-nginx

# Forcer la suppression d'un conteneur actif
docker rm -f mon-nginx

# Supprimer tous les conteneurs arrêtés
docker container prune

Inspection et logs

# Voir les logs d'un conteneur
docker logs mon-nginx

# Suivre les logs en temps réel
docker logs -f mon-nginx

# Inspecter un conteneur (configuration complète)
docker inspect mon-nginx

# Voir les processus dans un conteneur
docker top mon-nginx

# Statistiques en temps réel
docker stats mon-nginx

# Accéder au shell d'un conteneur actif
docker exec -it mon-nginx /bin/bash

# Exécuter une commande dans un conteneur
docker exec mon-nginx ls -la /etc/nginx

5. Exemple pratique : Serveur Web Apache

Méthode 1 : Image officielle simple

# Télécharger l'image Apache (httpd)
docker pull httpd:2.4

# Démarrer Apache avec un site web local
docker run -d \
  --name mon-apache \
  -p 8080:80 \
  -v /chemin/vers/mon-site:/usr/local/apache2/htdocs/ \
  httpd:2.4

# Créer un fichier index.html
echo '

Hello Docker!

' > /chemin/vers/mon-site/index.html # Accéder à http://localhost:8080

Méthode 2 : Avec configuration personnalisée

# Structure du projet
mon-projet/
├── html/
│   └── index.html
└── conf/
    └── httpd.conf

# Démarrer avec configuration custom
docker run -d \
  --name mon-apache-custom \
  -p 8080:80 \
  -v $(pwd)/html:/usr/local/apache2/htdocs/ \
  -v $(pwd)/conf/httpd.conf:/usr/local/apache2/conf/httpd.conf \
  httpd:2.4

Commandes utiles pour cet exemple

# Voir les logs Apache
docker logs -f mon-apache

# Tester la configuration Apache
docker exec mon-apache httpd -t

# Recharger la configuration
docker exec mon-apache httpd -k graceful

# Copier un fichier dans le conteneur
docker cp index.html mon-apache:/usr/local/apache2/htdocs/

# Copier un fichier depuis le conteneur
docker cp mon-apache:/usr/local/apache2/conf/httpd.conf ./backup.conf

6. Réseau Docker

Types de réseaux

# Bridge (défaut) : Réseau privé sur l'hôte
docker network create mon-reseau

# Host : Utilise directement le réseau de l'hôte
docker run --network host nginx

# None : Pas de réseau
docker run --network none nginx

# Lister les réseaux
docker network ls

# Inspecter un réseau
docker network inspect mon-reseau

# Connecter un conteneur à un réseau
docker network connect mon-reseau mon-apache

# Déconnecter
docker network disconnect mon-reseau mon-apache

Communication entre conteneurs

# Créer un réseau personnalisé
docker network create app-network

# Démarrer une base de données
docker run -d \
  --name mysql-db \
  --network app-network \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=myapp \
  mysql:8.0

# Démarrer une application web
docker run -d \
  --name webapp \
  --network app-network \
  -p 8080:80 \
  -e DB_HOST=mysql-db \
  -e DB_NAME=myapp \
  mon-image-app

# L'app peut accéder à la DB via le nom "mysql-db"

7. Volumes Docker

Pourquoi utiliser des volumes ?

Types de volumes

# Volume nommé (géré par Docker)
docker volume create mon-volume
docker run -d -v mon-volume:/var/lib/mysql mysql:8.0

# Bind mount (dossier hôte)
docker run -d -v /chemin/hote:/chemin/conteneur nginx

# Volume anonyme (temporaire)
docker run -d -v /var/lib/mysql mysql:8.0

# Lister les volumes
docker volume ls

# Inspecter un volume
docker volume inspect mon-volume

# Supprimer un volume
docker volume rm mon-volume

# Nettoyer les volumes non utilisés
docker volume prune

Exemple : Base de données persistante

# Créer un volume pour MySQL
docker volume create mysql-data

# Démarrer MySQL avec le volume
docker run -d \
  --name mysql-persistent \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  mysql:8.0

# Les données survivent même si on supprime le conteneur
docker rm -f mysql-persistent

# Redémarrer avec le même volume = données préservées
docker run -d \
  --name mysql-persistent-2 \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  mysql:8.0

8. Exemple complet : Stack LAMP

Architecture

┌─────────────────────────────────────┐
│  Navigateur → http://localhost:8080 │
└─────────────┬───────────────────────┘
              │
┌─────────────▼───────────────────────┐
│  Apache + PHP (port 8080→80)        │
│  Volume: ./html → /var/www/html     │
└─────────────┬───────────────────────┘
              │ app-network
┌─────────────▼───────────────────────┐
│  MySQL 8.0 (port 3306)              │
│  Volume: mysql-data → /var/lib/mysql│
└─────────────────────────────────────┘

Étape par étape

# 1. Créer le réseau
docker network create lamp-network

# 2. Créer le volume pour MySQL
docker volume create mysql-data

# 3. Démarrer MySQL
docker run -d \
  --name lamp-mysql \
  --network lamp-network \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=rootpass \
  -e MYSQL_DATABASE=myapp \
  -e MYSQL_USER=appuser \
  -e MYSQL_PASSWORD=apppass \
  mysql:8.0

# 4. Démarrer Apache+PHP
docker run -d \
  --name lamp-apache \
  --network lamp-network \
  -p 8080:80 \
  -v $(pwd)/html:/var/www/html \
  php:8.2-apache

# 5. Installer mysqli dans le conteneur PHP
docker exec lamp-apache docker-php-ext-install mysqli

# 6. Redémarrer Apache pour charger mysqli
docker restart lamp-apache

Fichier de test : html/index.php

<?php
// Connexion à MySQL
$host = 'lamp-mysql';  // Nom du conteneur MySQL
$db   = 'myapp';
$user = 'appuser';
$pass = 'apppass';

try {
    $pdo = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
    echo "<h1>Connexion réussie !</h1>";
    echo "<p>Version MySQL : " . $pdo->query('SELECT VERSION()')->fetchColumn() . "</p>";
    
    // Créer une table de test
    $pdo->exec("CREATE TABLE IF NOT EXISTS visitors (
        id INT AUTO_INCREMENT PRIMARY KEY,
        visit_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )");
    
    // Insérer une visite
    $pdo->exec("INSERT INTO visitors () VALUES ()");
    
    // Compter les visites
    $count = $pdo->query("SELECT COUNT(*) FROM visitors")->fetchColumn();
    echo "<p>Nombre de visites : $count</p>";
    
} catch (PDOException $e) {
    echo "<h1>Erreur !</h1>";
    echo "<p>" . $e->getMessage() . "</p>";
}

phpinfo();
?>

Commandes de gestion

# Voir les logs
docker logs lamp-apache
docker logs lamp-mysql

# Accéder au shell MySQL
docker exec -it lamp-mysql mysql -u root -prootpass

# Accéder au shell Apache
docker exec -it lamp-apache bash

# Arrêter la stack
docker stop lamp-apache lamp-mysql

# Redémarrer la stack
docker start lamp-mysql lamp-apache

# Tout supprimer (ATTENTION : données perdues si pas de volume)
docker rm -f lamp-apache lamp-mysql
docker network rm lamp-network
# Pour garder les données, ne pas supprimer le volume mysql-data

9. Bonnes pratiques

Limiter les ressources

# Limiter la mémoire et le CPU
docker run -d \
  --name app-limited \
  --memory="512m" \
  --cpus="1.0" \
  nginx

# Monitoring des ressources
docker stats app-limited

10. Commandes de nettoyage

# Supprimer tous les conteneurs arrêtés
docker container prune

# Supprimer toutes les images non utilisées
docker image prune -a

# Supprimer tous les volumes non utilisés
docker volume prune

# Supprimer tous les réseaux non utilisés
docker network prune

# NETTOYAGE COMPLET (ATTENTION !)
docker system prune -a --volumes

# Voir l'espace disque utilisé
docker system df

Défi progression (vers expert)

Mission: prendre une application locale et la conteneuriser avec persistance et monitoring de base.

← Retour aux tutoriels | Partie 2 : Dockerfile et Docker Compose →