Chapitre 1 : Introduction aux conteneurs¶
Objectifs du chapitre
- Expliquer le problème que résolvent les conteneurs
- Comparer un conteneur et une machine virtuelle
- Décrire les mécanismes du noyau Linux qui isolent et limitent un conteneur (namespaces et cgroups)
- Décrire l'architecture de Docker : client, daemon, containerd, runc
- Situer les normes OCI et choisir votre environnement de TP
- Acquis d'apprentissage visé : AA1
1. Pourquoi les conteneurs ?¶
Une application dépend de son environnement : version du langage, bibliothèques, fichiers de configuration, système. Quand l'un de ces éléments diffère entre le poste du développeur, la machine de test et le serveur de production, l'application se comporte autrement. C'est le célèbre « ça marche chez moi ».
Un conteneur résout ce problème en regroupant l'application et tout ce dont elle a besoin pour s'exécuter dans un ensemble isolé et portable. Le même ensemble s'exécute de la même façon sur le poste d'un étudiant, sur un serveur ou dans le cloud.
| Besoin | Apport des conteneurs |
|---|---|
| Reproduire un environnement | L'application et ses dépendances sont décrites une fois et réutilisées partout |
| Démarrer vite | Un conteneur démarre en général en quelques secondes ou moins |
| Occuper peu de ressources | Les conteneurs partagent le noyau de la machine hôte |
| Isoler les applications | Chaque conteneur a sa propre vue des processus, du réseau et des fichiers |
2. Conteneur et machine virtuelle¶
Une machine virtuelle (VM) simule une machine complète : un hyperviseur lui fournit du matériel virtuel et elle embarque son propre système d'exploitation, noyau compris. Un conteneur n'embarque pas de noyau : il s'exécute comme un processus de la machine hôte, sur le noyau de l'hôte, mais isolé des autres.
flowchart TB
subgraph VM["Machines virtuelles"]
direction TB
A1["App A + bibliothèques"] --> OS1["Système invité 1 (noyau)"]
A2["App B + bibliothèques"] --> OS2["Système invité 2 (noyau)"]
OS1 --> H["Hyperviseur"]
OS2 --> H
H --> M1["Matériel"]
end
subgraph CT["Conteneurs"]
direction TB
C1["App A + bibliothèques"] --> E["Moteur de conteneurs"]
C2["App B + bibliothèques"] --> E
E --> OSH["Système hôte (un seul noyau)"]
OSH --> M2["Matériel"]
end
| Critère | Machine virtuelle | Conteneur |
|---|---|---|
| Noyau | Un noyau par VM | Le noyau de l'hôte, partagé |
| Taille | En général de l'ordre du gigaoctet | En général de l'ordre de la dizaine à la centaine de mégaoctets |
| Démarrage | Quelques dizaines de secondes à quelques minutes | Quelques secondes ou moins |
| Isolation | Forte (noyau séparé) | Plus légère (noyau partagé) |
| Usage typique | Faire tourner un système complet | Faire tourner une application et ses dépendances |
Conteneurs et machines virtuelles se complètent
Dans ce cours, vous exécuterez des conteneurs dans des machines virtuelles. Les deux technologies ne s'opposent pas : on les combine très souvent.
Un conteneur Linux a besoin d'un noyau Linux
Un conteneur Linux partage le noyau Linux de son hôte. Sous Windows, Docker Desktop exécute donc le moteur dans une machine virtuelle Linux interne. C'est l'une des différences entre les options de TP décrites dans l'annexe Environnement.
3. Ce qui isole un conteneur : namespaces et cgroups¶
Un conteneur n'est pas un objet magique : c'est un processus ordinaire auquel le noyau Linux applique deux mécanismes.
3.1 Les namespaces : isoler ce que le processus voit¶
Un namespace (espace de noms) donne à un processus sa propre vue d'une ressource du système. Docker en utilise plusieurs pour chaque conteneur :
| Namespace | Ce qui est isolé | Effet dans le conteneur |
|---|---|---|
| PID | Les identifiants de processus | Le conteneur ne voit que ses propres processus ; son premier processus a le numéro 1 |
| NET | La pile réseau | Le conteneur a ses propres interfaces, adresse IP et table de routage |
| MNT | Les points de montage | Le conteneur a son propre système de fichiers |
| UTS | Le nom d'hôte | Le conteneur a son propre nom de machine |
| IPC | La communication entre processus | Les échanges mémoire entre processus sont propres au conteneur |
| USER | Les identifiants d'utilisateurs | Un utilisateur du conteneur peut correspondre à un autre utilisateur de l'hôte |
3.2 Les cgroups : limiter ce que le processus consomme¶
Les cgroups (control groups) permettent de mesurer et de limiter les ressources utilisées par un groupe de processus : processeur, mémoire, entrées-sorties disque, nombre de processus. Sans limite, un conteneur peut consommer toutes les ressources de l'hôte.
| Mécanisme | Question à laquelle il répond | Exemple |
|---|---|---|
| Namespaces | « Que peut voir ce processus ? » | Il ne voit pas les processus des autres conteneurs |
| Cgroups | « Combien peut consommer ce processus ? » | Il ne peut pas utiliser plus de 512 Mo de mémoire |
Idée à retenir
Un conteneur = un processus + des namespaces (isolation) + des cgroups (limites) + un système de fichiers propre. Il n'y a ni machine ni noyau supplémentaire.
4. L'architecture de Docker¶
Docker est la plateforme qui rend ces mécanismes simples à utiliser. Elle repose sur une architecture client-serveur.
flowchart LR
U["Vous"] --> CLI["Client Docker<br/>(commande docker)"]
CLI -- "API REST" --> D["Daemon dockerd"]
D --> CD["containerd"]
CD --> R["runc"]
R --> K["Conteneur<br/>(processus isolé)"]
D <--> REG[("Registre<br/>(Docker Hub)")]
| Composant | Rôle |
|---|---|
Client Docker (docker) |
La commande que vous tapez. Il envoie vos demandes au daemon et affiche les résultats. |
Daemon (dockerd) |
Le service qui reçoit les demandes du client et gère images, conteneurs, réseaux et volumes. |
| containerd | Le gestionnaire de bas niveau : il gère le cycle de vie des conteneurs et le stockage des images pour le daemon. |
| runc | L'outil qui crée réellement le conteneur en demandant au noyau les namespaces et les cgroups. |
| Registre | Un service qui stocke et distribue des images. Docker Hub est le registre public par défaut. |
Le client et le daemon peuvent se trouver sur la même machine (cas de vos TP) ou sur des machines différentes : ils communiquent par une API.
Les trois objets à connaître¶
Trois mots reviendront tout au long du cours :
| Objet | Définition | Analogie |
|---|---|---|
| Image | Modèle en lecture seule qui contient l'application et ses dépendances | La recette |
| Conteneur | Instance en cours d'exécution (ou arrêtée) d'une image | Le plat préparé |
| Registre | Service qui stocke et partage les images | Le livre de recettes partagé |
Plusieurs conteneurs peuvent être créés à partir de la même image. La construction des images est étudiée au chapitre 3 et leur distribution au chapitre 4.
5. Les normes OCI¶
Pour éviter qu'un fournisseur ne soit propriétaire du format des conteneurs, l'industrie a créé l'Open Container Initiative (OCI). Elle publie trois spécifications :
| Spécification | Ce qu'elle définit |
|---|---|
| Image | Le format d'une image de conteneur |
| Runtime | La manière d'exécuter un conteneur à partir d'une image |
| Distribution | La manière de publier et de télécharger des images depuis un registre |
Grâce à ces normes, une image construite avec Docker peut être exécutée par d'autres outils compatibles OCI. runc est l'implémentation de référence de la spécification runtime.
6. Votre environnement de TP¶
Vous choisissez parmi trois options : Docker Desktop, Ubuntu Desktop ou Ubuntu Server dans une machine virtuelle. Elles sont comparées dans l'annexe Environnement, qui précise aussi les ressources nécessaires et les tests de validation. Vous installez et validez Docker au Lab 1.1.
À retenir
- Un conteneur est un processus isolé qui partage le noyau de l'hôte ; il est plus léger et plus rapide à démarrer qu'une machine virtuelle.
- Les namespaces isolent ce que le processus voit ; les cgroups limitent ce qu'il consomme.
- Docker repose sur un client (
docker) qui parle à un daemon (dockerd), lequel s'appuie sur containerd et runc. - Une image est un modèle ; un conteneur en est une instance ; un registre stocke les images.
- Les normes OCI rendent images et conteneurs portables d'un outil à l'autre.
Pour vérifier votre compréhension¶
Pourquoi un conteneur démarre-t-il beaucoup plus vite qu'une machine virtuelle ?
Il n'embarque pas de système d'exploitation ni de noyau : c'est un simple processus de la machine hôte, isolé par le noyau. Il n'y a donc pas de système à démarrer.
Quelle est la différence entre un namespace et un cgroup ?
Un namespace limite ce que le processus voit (processus, réseau, fichiers, nom d'hôte). Un cgroup limite ce qu'il consomme (processeur, mémoire, entrées-sorties).
Vous tapez une commande docker : quel composant la reçoit, et quel composant crée finalement le conteneur ?
Le daemon dockerd reçoit la demande envoyée par le client. Il s'appuie sur containerd, puis runc crée le conteneur en s'adressant au noyau.