Lexique · DevOps / Cloud / Data

Container : définition, fonctionnement et différences avec une VM

Le principe d'isolation qui permet d'emballer une application avec ses dépendances et de l'exécuter partout de la même façon : mécanismes du noyau Linux, standards OCI, runtimes, comparaison avec la machine virtuelle et sécurité.

Par Équipe Blent· Mis à jour le · 15 min de lecture· Niveau intermédiaire

Container en bref

Traduction
Conteneur
Type
Isolation au niveau du système d'exploitation
Briques du noyau Linux
Namespaces, cgroups, capabilities, seccomp
Standard
Open Container Initiative (OCI), créée en 2015
Runtimes courants
containerd, CRI-O, runc, crun
Ancêtres
chroot, FreeBSD Jails, Solaris Zones, LXC

Définition : Container

Un container, ou conteneur, est un environnement d'exécution isolé qui regroupe une application et tout ce dont elle a besoin pour fonctionner : bibliothèques, dépendances, fichiers de configuration. Contrairement à une machine virtuelle, il n'embarque pas de système d'exploitation complet : il partage le noyau de la machine hôte, qui l'isole des autres processus grâce à des mécanismes comme les namespaces et les cgroups sous Linux. Un conteneur est créé à partir d'une image, un paquet immuable et portable décrit par les standards de l'Open Container Initiative. Il démarre en quelques secondes et se comporte de la même façon sur un poste de développement, un serveur ou un cluster Cloud.

En une phrase : un container est un processus isolé par le noyau, livré avec ses dépendances, qui s'exécute de la même façon partout.

Dans cette définition

Qu'est-ce qu'un container ?

Un container est un processus, ou un groupe de processus, que le noyau du système d'exploitation exécute dans un environnement isolé. Vu de l'intérieur, il croit disposer de sa propre machine : son système de fichiers, ses processus, son interface réseau, son nom d'hôte. Vu de l'hôte, c'est un processus presque ordinaire, simplement cloisonné et limité en ressources.

L'idée est ancienne. L'appel système chroot, apparu sur Unix en 1979, isolait déjà l'arborescence de fichiers d'un processus. Les FreeBSD Jails (2000) puis les Solaris Zones (2004) ont étendu ce cloisonnement aux processus et au réseau. Sous Linux, les namespaces et les cgroups, ces derniers proposés par des ingénieurs de Google et intégrés au noyau en 2008, ont permis l'apparition de LXC. C'est en 2013 que Docker rend le conteneur accessible à tous les développeurs, en y ajoutant un format d'image simple et partageable. En 2015, l'Open Container Initiative (OCI) est créée sous l'égide de la Linux Foundation pour standardiser ces formats.

Le conteneur se situe entre le simple processus et la machine virtuelle. Il isole l'application et ses dépendances sans virtualiser le matériel ni démarrer un second système d'exploitation. C'est ce qui le rend léger, rapide et portable, et ce qui en a fait l'unité de base des architectures Cloud natives, orchestrées par Kubernetes.

À retenir : un conteneur n'est pas une petite machine virtuelle. C'est un processus de l'hôte, que le noyau isole et limite. Docker, Podman ou containerd ne sont que des outils pour en créer.

Comment fonctionne un container ?

Quel que soit l'outil utilisé pour le lancer, un conteneur suit toujours le même cycle, de l'image stockée dans un registre jusqu'au processus isolé qui tourne sur l'hôte.

  1. Construire une image

    L'image est un ensemble de couches de système de fichiers en lecture seule, accompagné d'un fichier de configuration : commande de démarrage, variables d'environnement, utilisateur, ports exposés.

  2. Récupérer l'image depuis un registre

    Le runtime télécharge les couches manquantes depuis un registre (Docker Hub, GitHub Container Registry, Harbor, registre Cloud) et vérifie leur empreinte SHA-256.

  3. Préparer le système de fichiers

    Les couches sont superposées, généralement avec OverlayFS, et une couche inscriptible propre au conteneur est ajoutée au sommet. L'image elle-même n'est jamais modifiée.

  4. Créer les namespaces

    Le runtime bas niveau place le processus dans de nouveaux namespaces : il obtient sa propre arborescence de processus, sa pile réseau, ses points de montage et son nom d'hôte.

  5. Limiter et restreindre

    Les cgroups plafonnent le CPU, la mémoire et les entrées-sorties. Les capabilities, seccomp et AppArmor ou SELinux réduisent ce que le processus a le droit de demander au noyau.

  6. Lancer le processus principal

    La commande définie dans l'image démarre et devient le PID 1 du conteneur. Quand ce processus s'arrête, le conteneur s'arrête avec lui.

Sous le capot : namespaces et cgroups

Deux familles de mécanismes du noyau Linux font l'essentiel du travail.

Les namespaces contrôlent ce qu'un processus voit. Chaque type de namespace isole une ressource :

  • PID : une arborescence de processus propre, où l'application est le PID 1.
  • mount : ses propres points de montage, donc son propre système de fichiers racine.
  • network : ses interfaces, adresses IP, tables de routage et ports.
  • UTS : son nom d'hôte.
  • IPC : ses files de messages et sa mémoire partagée.
  • user : une correspondance entre l'utilisateur root du conteneur et un utilisateur sans privilège sur l'hôte.
  • cgroup et time : sa vue de la hiérarchie des cgroups et de certaines horloges.

Les cgroups (control groups) contrôlent ce qu'un processus consomme : quota de CPU, plafond de mémoire, débit disque, nombre maximal de processus. Si un conteneur dépasse sa limite mémoire, le noyau l'arrête sans affecter ses voisins.

Il est possible d'observer ces mécanismes sans aucun outil de conteneurisation, avec la commande unshare :

bash
# Ouvrir un shell dans de nouveaux namespaces PID, mount, UTS et réseau
sudo unshare --pid --fork --mount-proc --uts --net bash

hostname demo-conteneur   # ne modifie que le namespace UTS
ps aux                    # le shell est le PID 1 et ne voit que ses enfants
ip link                   # seule l'interface loopback existe
ls -l /proc/$$/ns         # identifiants des namespaces du processus

Un runtime comme runc fait exactement cela, en plus complet : il crée les namespaces, rattache le processus à un cgroup, change sa racine vers le système de fichiers de l'image, retire les privilèges inutiles, puis lance la commande prévue.

Image, conteneur et runtime : le vocabulaire OCI

Image et conteneur

L'image est le paquet livrable : une pile de couches de fichiers en lecture seule et un manifeste qui décrit la configuration. Elle est identifiée par une empreinte (digest) SHA-256 et, pour les humains, par un nom et un tag, comme python:3.12-slim. Le conteneur est une instance vivante de cette image, avec une couche inscriptible au-dessus. Une image est au conteneur ce qu'une classe est à un objet.

Les trois spécifications OCI

L'Open Container Initiative maintient trois spécifications qui garantissent l'interopérabilité :

  • image-spec : le format des images, de leurs couches et de leur manifeste ;
  • runtime-spec : la façon d'exécuter un conteneur à partir d'un système de fichiers et d'une configuration ;
  • distribution-spec : l'API HTTP des registres pour pousser et tirer des images.

Grâce à elles, une image construite avec Docker s'exécute avec Podman, containerd ou CRI-O, et se stocke dans n'importe quel registre conforme.

Runtimes haut niveau et bas niveau

L'exécution est découpée en deux étages. Un runtime haut niveau (containerd, CRI-O) gère les images, le stockage, le réseau et le cycle de vie des conteneurs. Il délègue la création effective du processus isolé à un runtime bas niveau conforme à l'OCI : runc, l'implémentation de référence, ou crun, écrit en C. Kubernetes dialogue avec le runtime haut niveau via la Container Runtime Interface (CRI) ; depuis la version 1.24 (2022), il n'utilise plus Docker Engine comme intermédiaire, ce qui ne change rien pour les images construites avec Docker.

Les registres

Un registre stocke et distribue les images : Docker Hub, GitHub Container Registry, Amazon ECR, Google Artifact Registry, Azure Container Registry, ou un registre auto-hébergé comme Harbor, qui ajoute contrôle d'accès, réplication et scan de vulnérabilités.

À quoi servent les containers ?

Le conteneur est devenu l'unité de livraison standard du logiciel côté serveur, du poste du développeur jusqu'à la production.

  • Environnements reproductibles

    Fini le « ça marche sur ma machine » : toute l'équipe exécute exactement la même image, versions de dépendances comprises.

  • Microservices

    Chaque service est livré, mis à l'échelle et mis à jour indépendamment, dans son propre conteneur.

  • Pipelines CI/CD

    Les jobs de build et de test tournent dans des conteneurs jetables, et l'artefact livré en production est une image versionnée.

  • Portabilité multi-cloud

    Une image OCI s'exécute sur un serveur sur site, sur un cluster managé ou sur un service serverless sans modification.

  • Déploiement de modèles d'IA

    Un modèle, son code d'inférence et ses bibliothèques (CUDA, PyTorch) sont figés ensemble dans une image déployable.

  • Densification des serveurs

    Plus légers qu'une machine virtuelle, les conteneurs permettent de faire tourner davantage d'applications sur le même matériel.

Quels sont les avantages des containers ?

La force du conteneur tient à un compromis : une isolation suffisante pour la plupart des usages, pour un coût bien inférieur à celui d'une machine virtuelle.

  • Démarrage en quelques secondes, voire moins, car aucun système d'exploitation ne doit démarrer.
  • Faible empreinte : pas de noyau ni de système complet à dupliquer pour chaque application.
  • Portabilité garantie par des formats d'image et d'exécution standardisés par l'OCI.
  • Immuabilité : une même image, identifiée par son empreinte, passe du test à la production sans changer.
  • Isolation des dépendances : deux applications aux versions incompatibles cohabitent sur le même hôte.
  • Base naturelle de l'automatisation : orchestration, mise à l'échelle et déploiements progressifs.

Quelles sont les limites des containers ?

Partager le noyau de l'hôte a des conséquences, en particulier sur la sécurité et sur la gestion des données.

  • Isolation plus faible qu'une machine virtuelle : une faille du noyau peut exposer tous les conteneurs de l'hôte.
  • Dépendance au noyau : un conteneur Linux a besoin d'un noyau Linux, d'où une VM légère sur macOS et Windows.
  • Données éphémères : tout ce qui est écrit hors d'un volume disparaît à la suppression du conteneur.
  • Chaîne d'approvisionnement à surveiller : une image de base vulnérable ou malveillante se propage partout.
  • Complexité opérationnelle à grande échelle : réseau, stockage, observabilité et orchestration sont à outiller.

Container ou machine virtuelle : quelles différences ?

La machine virtuelle virtualise le matériel ; le conteneur virtualise le système d'exploitation. Notre article Virtualisation : tout comprendre détaille le fonctionnement des hyperviseurs.

CritèreContainerMachine virtuelle
Niveau d'isolationSystème d'exploitation (noyau partagé)Matériel (noyau dédié)
Composant cléRuntime de conteneursHyperviseur (KVM, VMware ESXi, Hyper-V)
ContenuApplication et dépendancesSystème d'exploitation complet et application
Taille typiqueQuelques dizaines à centaines de MoPlusieurs Go
DémarrageUne seconde ou moinsDe plusieurs secondes à quelques minutes
Systèmes invitésMême noyau que l'hôteN'importe quel système compatible avec le matériel
SécuritéBonne, mais surface d'attaque du noyau partagéeFrontière d'isolation plus forte
Usage typeMicroservices, CI/CD, déploiements fréquentsSystèmes hétérogènes, multi-locataire strict, logiciels anciens

Les deux se combinent. Dans le Cloud, les conteneurs tournent presque toujours dans des machines virtuelles : la VM isole les clients entre eux, le conteneur découpe les applications à l'intérieur.

Sécuriser ses containers

Partager le noyau impose une discipline particulière. Les bonnes pratiques relèvent de la démarche DevSecOps et portent sur trois niveaux.

  • L'image : partir d'une image de base minimale (slim, Alpine, distroless), la reconstruire régulièrement, la scanner avec un outil comme Trivy et la signer, par exemple avec cosign du projet Sigstore.
  • Les privilèges : ne pas exécuter le processus en root, retirer les capabilities inutiles, conserver le profil seccomp par défaut, monter le système de fichiers racine en lecture seule et bannir le mode privilégié.
  • L'isolation : activer les user namespaces ou le mode rootless, et réserver un runtime sandboxé (gVisor, Kata Containers) aux charges qui exécutent du code non fiable.

Ces règles s'automatisent : un pipeline CI/CD peut refuser une image vulnérable, et un orchestrateur peut interdire les conteneurs privilégiés par politique.

Quand utiliser des containers ?

Le conteneur est aujourd'hui le choix par défaut pour une application serveur. Il reste des cas où une autre forme d'isolation est plus adaptée.

Pertinent si

Le conteneur est le bon choix

  • Vous livrez une application web, une API ou un traitement batch.
  • Plusieurs environnements doivent rester strictement identiques.
  • Vous voulez automatiser build, test et déploiement.
  • L'application doit pouvoir être mise à l'échelle rapidement.
Moins adapté si

Une autre isolation s'impose

  • La charge exige un noyau ou un système d'exploitation différent de l'hôte.
  • Vous exécutez du code non fiable, sans runtime sandboxé.
  • L'application dépend fortement du matériel ou d'un pilote spécifique.
  • Un logiciel ancien n'a jamais été prévu pour être découpé ni conteneurisé.

Outils et runtimes de containers

L'écosystème se répartit entre les outils qui construisent les images, les runtimes qui les exécutent, les registres qui les stockent et les orchestrateurs qui les pilotent.

Les concepts à connaître autour des containers

Le conteneur se comprend mieux en le situant parmi les autres notions de l'infrastructure moderne.

Ressources pour approfondir les containers

Trois articles du blog Blent pour passer du concept à la pratique.

Questions fréquentes

Questions fréquentes

Les deux désignent la même chose. « Container » est le terme anglais, très utilisé dans les équipes techniques ; « conteneur » est sa traduction française, recommandée dans les textes officiels. Le mot vient de l'analogie avec le conteneur maritime, une boîte standard qui se transporte de la même façon quel que soit son contenu.

Expertise

À propos de l'auteur

Équipe Blent

Les ingénieurs et mentors Blent conçoivent, automatisent et mettent en production des infrastructures Cloud, et forment chaque année des centaines de professionnels au DevOps.

Sources et méthodologie

  • Spécifications de l'Open Container Initiative : runtime-spec, image-spec, distribution-spec
  • Pages de manuel Linux : namespaces(7), cgroups(7), unshare(1)
  • Documentation de containerd, CRI-O et Kubernetes (Container Runtime Interface)
  • Retours d'expérience des projets et formations Blent