Aller au contenu
  1. Blog/

Apprendre Docker : comprendre les conteneurs et l'architecture

·12 mins
Sommaire
Apprendre Docker - Cet article fait partie d'une série.
Partie 1: Cet article

Introduction
#

Docker a transformé la façon dont on développe, teste et déploie des applications. Avant Docker, déployer une application signifiait souvent jongler avec des dépendances, des configurations système différentes entre la machine du développeur et le serveur de production, et des scripts d’installation fragiles. Aujourd’hui, Docker permet d’empaqueter une application avec tout ce dont elle a besoin dans un format portable et reproductible : le conteneur.

Ce premier chapitre pose les fondations. On va comprendre ce qu’est un conteneur, en quoi il diffère d’une machine virtuelle, comment Docker est architecturé, et on terminera par vos premières commandes. Pas de panique si vous partez de zéro — c’est exactement le point de départ.


Qu’est-ce qu’un conteneur ?
#

Un conteneur est un environnement d’exécution isolé qui partage le noyau (kernel) du système hôte. Il embarque le code de l’application, ses dépendances, ses bibliothèques et sa configuration — tout ce qu’il faut pour que l’application tourne, sans interférer avec le reste du système.

Concrètement, un conteneur c’est :

  • Un processus isolé — il voit son propre système de fichiers, ses propres interfaces réseau, ses propres processus
  • Léger — il ne contient pas de système d’exploitation complet, juste les couches nécessaires
  • Éphémère — il peut être créé, détruit et recréé en quelques secondes
  • Portable — il tourne de la même façon sur votre laptop, un serveur de staging ou un cluster Kubernetes

Le problème que Docker résout
#

Vous avez sûrement déjà entendu (ou prononcé) cette phrase :

« Ça marche sur ma machine. »

Ce problème classique vient du fait que l’environnement de développement diffère de l’environnement de production : versions de Python différentes, bibliothèques manquantes, configurations système incompatibles. Docker élimine ce problème en garantissant que l’environnement voyage avec l’application.


Conteneurs vs Machines Virtuelles
#

C’est la question que tout le monde se pose en découvrant Docker. Les deux technologies permettent d’isoler des applications, mais elles fonctionnent à des niveaux très différents.

Machine Virtuelle (VM)
#

Une VM émule un ordinateur complet : matériel virtuel, système d’exploitation invité, noyau dédié. C’est comme avoir un ordinateur dans un ordinateur.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
┌─────────────────────────────────────────────────┐
│              Machine physique (Hôte)             │
├─────────────────────────────────────────────────┤
│              Système d'exploitation              │
├─────────────────────────────────────────────────┤
│                   Hyperviseur                    │
│            (VirtualBox, VMware, KVM)             │
├───────────────┬───────────────┬─────────────────┤
│     VM 1      │     VM 2      │      VM 3       │
│ ┌───────────┐ │ ┌───────────┐ │ ┌─────────────┐ │
│ │  App A    │ │ │  App B    │ │ │   App C     │ │
│ │  Libs     │ │ │  Libs     │ │ │   Libs      │ │
│ │  OS invité│ │ │  OS invité│ │ │  OS invité  │ │
│ │  Kernel   │ │ │  Kernel   │ │ │  Kernel     │ │
│ └───────────┘ │ └───────────┘ │ └─────────────┘ │
└───────────────┴───────────────┴─────────────────┘

Chaque VM possède son propre noyau et son propre OS. Résultat : c’est lourd. Une VM Ubuntu pèse facilement 2 à 4 Go et met 30 secondes à démarrer.

Conteneur
#

Un conteneur partage le noyau de l’hôte. Il n’embarque que l’application et ses dépendances — pas de système d’exploitation complet.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
┌─────────────────────────────────────────────────┐
│              Machine physique (Hôte)             │
├─────────────────────────────────────────────────┤
│         Système d'exploitation + Kernel          │
├─────────────────────────────────────────────────┤
│                 Docker Engine                    │
├───────────────┬───────────────┬─────────────────┤
│ Conteneur 1   │ Conteneur 2   │  Conteneur 3    │
│ ┌───────────┐ │ ┌───────────┐ │ ┌─────────────┐ │
│ │  App A    │ │ │  App B    │ │ │   App C     │ │
│ │  Libs     │ │ │  Libs     │ │ │   Libs      │ │
│ └───────────┘ │ └───────────┘ │ └─────────────┘ │
└───────────────┴───────────────┴─────────────────┘

Pas de noyau dupliqué, pas d’OS invité. Un conteneur pèse quelques mégaoctets et démarre en moins d’une seconde.

Comparaison synthétique
#

CritèreMachine VirtuelleConteneur
IsolationComplète (noyau séparé)Processus (noyau partagé)
TailleGigaoctetsMégaoctets
DémarrageMinutesSecondes
PerformanceOverhead de virtualisationQuasi-native
PortabilitéLimitée (image lourde)Excellente
SécuritéForte (isolation matérielle)Bonne (mais surface d’attaque noyau)

Important : les conteneurs ne remplacent pas les VMs. Ce sont des outils complémentaires. On utilise souvent des conteneurs dans des VMs en production pour combiner les avantages des deux.


L’architecture Docker
#

Docker n’est pas un outil monolithique. C’est un ensemble de composants qui collaborent selon une architecture client-serveur. Comprendre ces composants, c’est comprendre comment Docker fonctionne sous le capot.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
┌──────────┐         API REST         ┌──────────────────┐
│          │ ◄──────────────────────►  │                  │
│  Docker  │                           │  Docker Daemon   │
│   CLI    │    docker run nginx       │   (dockerd)      │
│          │ ──────────────────────►   │                  │
└──────────┘                           │  ┌────────────┐  │
                                       │  │ Containers │  │
                                       │  ├────────────┤  │
                                       │  │   Images   │  │
                                       │  ├────────────┤  │
                                       │  │  Networks  │  │
                                       │  ├────────────┤  │
                                       │  │  Volumes   │  │
                                       │  └────────────┘  │
                                       └────────┬─────────┘
                                       ┌──────────────────┐
                                       │    Registry       │
                                       │  (Docker Hub)     │
                                       └──────────────────┘

Docker CLI (le client)
#

C’est l’outil en ligne de commande que vous utilisez au quotidien. Quand vous tapez docker run, docker build ou docker ps, vous interagissez avec le client Docker. Il traduit vos commandes en appels à l’API REST du daemon.

Docker Daemon (dockerd)
#

Le daemon est le moteur de Docker. C’est un processus en arrière-plan qui gère tout : la création des conteneurs, le téléchargement des images, la gestion du réseau et des volumes. Il écoute les requêtes du client et les exécute.

Le daemon utilise en interne containerd et runc pour créer et gérer les conteneurs au niveau du système d’exploitation.

Images Docker
#

Une image est un modèle en lecture seule qui contient tout ce qu’il faut pour exécuter une application : code source, runtime, bibliothèques, variables d’environnement et fichiers de configuration.

Les images sont construites en couches (layers). Chaque instruction dans un Dockerfile ajoute une couche. Ce système de couches permet :

  • Le partage : plusieurs images peuvent réutiliser les mêmes couches de base
  • La mise en cache : seules les couches modifiées sont reconstruites
  • L’efficacité : le stockage est optimisé grâce à la déduplication

Conteneurs
#

Un conteneur est une instance en cours d’exécution d’une image. Si l’image est le plan de la maison, le conteneur est la maison construite. Vous pouvez créer plusieurs conteneurs à partir de la même image — chacun avec son propre état.

Un conteneur ajoute une couche inscriptible au-dessus des couches en lecture seule de l’image. Quand le conteneur est supprimé, cette couche disparaît.

Registry (Docker Hub)
#

Un registry est un dépôt d’images. Docker Hub est le registry public par défaut — c’est là que vous trouverez les images officielles de Nginx, PostgreSQL, Node.js, Python, etc.

Vous pouvez aussi utiliser des registries privés (GitHub Container Registry, GitLab Registry, AWS ECR, Harbor…) pour stocker vos propres images.


Installation de Docker
#

Sur Ubuntu (22.04 / 24.04)
#

On installe Docker Engine depuis les dépôts officiels — pas la version des dépôts Ubuntu, qui est souvent obsolète.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. Mettre à jour les paquets et installer les prérequis
sudo apt update
sudo apt install -y ca-certificates curl gnupg

# 2. Ajouter la clé GPG officielle de Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

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

# 4. Installer Docker Engine
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 5. Ajouter votre utilisateur au groupe docker (évite d'utiliser sudo)
sudo usermod -aG docker $USER

Note : après l’ajout au groupe docker, déconnectez-vous et reconnectez-vous (ou exécutez newgrp docker) pour que le changement prenne effet.

Sur macOS
#

Sur macOS, Docker ne tourne pas nativement (le noyau Linux n’est pas disponible). On utilise Docker Desktop, qui crée une VM Linux légère en arrière-plan.

  1. Téléchargez Docker Desktop depuis docker.com/products/docker-desktop
  2. Ouvrez le fichier .dmg et glissez Docker dans Applications
  3. Lancez Docker Desktop depuis le Launchpad

Docker Desktop inclut le CLI, le daemon, Docker Compose et une interface graphique.

Alternative : si vous préférez un outil open source et léger, jetez un œil à Colima (brew install colima), qui fournit un runtime Docker sans l’interface graphique.

Vérifier l’installation
#

Quelle que soit votre plateforme :

1
2
3
4
5
# Vérifier la version installée
docker --version

# Tester que tout fonctionne
docker run hello-world

Si vous voyez le message « Hello from Docker! », tout est en place.


Premiers pas avec Docker
#

On passe à la pratique. Voici les commandes essentielles pour démarrer.

docker run — lancer un conteneur
#

C’est la commande la plus utilisée. Elle crée et démarre un conteneur à partir d’une image.

1
2
# Lancer un conteneur Nginx en arrière-plan
docker run -d --name mon-nginx -p 8080:80 nginx

Décomposons :

  • -d : mode détaché (le conteneur tourne en arrière-plan)
  • --name mon-nginx : donne un nom au conteneur (plus pratique qu’un ID aléatoire)
  • -p 8080:80 : publie le port 80 du conteneur sur le port 8080 de l’hôte
  • nginx : le nom de l’image à utiliser

Ouvrez votre navigateur sur http://localhost:8080 — vous devriez voir la page d’accueil de Nginx. Vous venez de déployer un serveur web en une seule commande.

Si l’image n’est pas présente localement, Docker la télécharge automatiquement depuis Docker Hub.

docker ps — lister les conteneurs
#

1
2
3
4
5
# Conteneurs en cours d'exécution
docker ps

# Tous les conteneurs (y compris les arrêtés)
docker ps -a

La sortie ressemble à :

1
2
CONTAINER ID   IMAGE   COMMAND                  STATUS         PORTS                  NAMES
a1b2c3d4e5f6   nginx   "/docker-entrypoint.…"   Up 2 minutes   0.0.0.0:8080->80/tcp   mon-nginx

Vous y retrouvez l’ID du conteneur, l’image source, le statut, les ports exposés et le nom.

docker logs — consulter les journaux
#

1
2
3
4
5
# Voir les logs du conteneur
docker logs mon-nginx

# Suivre les logs en temps réel (comme tail -f)
docker logs -f mon-nginx

C’est votre premier réflexe quand quelque chose ne fonctionne pas. Les logs d’un conteneur correspondent à ce que le processus principal envoie sur stdout et stderr.

docker exec — exécuter une commande dans un conteneur
#

1
2
3
4
5
# Ouvrir un shell interactif dans le conteneur
docker exec -it mon-nginx bash

# Exécuter une commande ponctuelle
docker exec mon-nginx cat /etc/nginx/nginx.conf
  • -i : mode interactif (garde stdin ouvert)
  • -t : alloue un terminal (pseudo-TTY)

C’est l’équivalent de « se connecter en SSH » à votre conteneur — sauf qu’on n’utilise pas SSH.

docker stop et docker rm — arrêter et supprimer
#

1
2
3
4
5
6
7
8
# Arrêter le conteneur
docker stop mon-nginx

# Supprimer le conteneur
docker rm mon-nginx

# Raccourci : forcer l'arrêt et supprimer
docker rm -f mon-nginx

Un conteneur arrêté existe encore sur le système (visible avec docker ps -a). Il faut le supprimer explicitement avec docker rm pour libérer les ressources.

docker images — gérer les images locales
#

1
2
3
4
5
# Lister les images téléchargées
docker images

# Supprimer une image
docker rmi nginx

Comprendre le cycle de vie d’un conteneur
#

Un conteneur passe par plusieurs états au cours de sa vie :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
  docker create        docker start        docker stop
      │                    │                    │
      ▼                    ▼                    ▼
 ┌─────────┐        ┌───────────┐        ┌───────────┐
 │ Created  │───────►│  Running  │───────►│  Stopped  │
 └─────────┘        └───────────┘        └───────────┘
                           │                    │
                           │   docker rm        │  docker rm
                           ▼                    ▼
                     ┌───────────┐        ┌───────────┐
                     │  Removed  │        │  Removed  │
                     └───────────┘        └───────────┘

La commande docker run est un raccourci qui combine docker create + docker start.

Un point crucial : les données écrites dans un conteneur sont perdues quand il est supprimé. Pour persister des données, on utilise des volumes — un sujet qu’on abordera dans un chapitre ultérieur.


Récapitulatif des commandes
#

CommandeDescription
docker run -d --name X -p H:C imageLancer un conteneur en arrière-plan
docker psLister les conteneurs actifs
docker ps -aLister tous les conteneurs
docker logs [-f] nomVoir les journaux d’un conteneur
docker exec -it nom bashOuvrir un shell dans un conteneur
docker stop nomArrêter un conteneur
docker rm nomSupprimer un conteneur
docker imagesLister les images locales
docker rmi imageSupprimer une image locale

Exercices pratiques
#

Mettez en pratique ce que vous venez d’apprendre. Essayez de résoudre chaque exercice avant de regarder la solution.

Exercice 1 — Lancer un serveur web
#

Objectif : démarrer un conteneur Nginx accessible sur le port 3000 de votre machine.

💡 Solution
1
2
docker run -d --name web-exo1 -p 3000:80 nginx
# Vérifier : ouvrir http://localhost:3000

Exercice 2 — Explorer un conteneur
#

Objectif : entrer dans le conteneur créé à l’exercice 1, lister les fichiers dans /usr/share/nginx/html/ et afficher le contenu de index.html.

💡 Solution
1
2
3
4
docker exec -it web-exo1 bash
ls /usr/share/nginx/html/
cat /usr/share/nginx/html/index.html
exit

Exercice 3 — Lancer une base de données
#

Objectif : démarrer un conteneur PostgreSQL avec les variables d’environnement nécessaires.

💡 Solution
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
docker run -d \
  --name ma-db \
  -e POSTGRES_USER=admin \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=cours_docker \
  -p 5432:5432 \
  postgres:16

# Vérifier que le conteneur tourne
docker ps

# Consulter les logs pour voir si PostgreSQL est prêt
docker logs ma-db

Exercice 4 — Observer et nettoyer
#

Objectif : lister tous vos conteneurs (actifs et arrêtés), arrêter ceux qui tournent, puis tout supprimer.

💡 Solution
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Lister tout
docker ps -a

# Tout arrêter
docker stop web-exo1 ma-db

# Tout supprimer
docker rm web-exo1 ma-db

# Vérifier qu'il ne reste rien
docker ps -a

Exercice 5 — Défi autonome
#

Objectif : sans regarder les exemples ci-dessus, lancez un conteneur httpd (Apache) nommé mon-apache, accessible sur le port 9090, puis affichez ses logs en temps réel et ouvrez un shell à l’intérieur. Quand vous avez terminé, nettoyez tout.


Ce qu’on a appris
#

Dans ce premier chapitre, vous avez découvert :

  • Ce qu’est un conteneur et pourquoi il est différent d’une machine virtuelle
  • L’architecture Docker : client CLI, daemon, images, conteneurs et registries
  • Comment installer Docker sur Ubuntu et macOS
  • Les commandes fondamentales : run, ps, logs, exec, stop, rm
  • Le cycle de vie d’un conteneur

Ce sont les briques de base. Tout le reste de Docker — Dockerfile, volumes, réseaux, Docker Compose, orchestration — repose sur ces fondamentaux.


La suite
#

Dans le chapitre suivant : Dockerfile et images, on apprendra à construire nos propres images. Fini de se contenter des images toutes faites — on va écrire un Dockerfile, comprendre les couches, optimiser la taille des images et publier sur un registry.

👉 Restez sur devopslab.ch pour la suite du cours.

Apprendre Docker - Cet article fait partie d'une série.
Partie 1: Cet article

Articles connexes