Chapitre 5.7Docker et les conteneurs

Embarquer une application avec tout ce dont elle a besoin.

4 minutes de lecture

"Ça marche sur ma machine." C'est la phrase que les développeurs détestent le plus. Un code qui fonctionne parfaitement chez le développeur plante en production parce que le serveur a une version différente du langage, une bibliothèque manquante ou une configuration légèrement différente.

Docker, lancé en 2013, a rendu ce problème beaucoup plus rare grâce au conteneur. Le mécanisme d'isolation existait déjà dans Linux depuis des années, mais il était réservé aux spécialistes. Le vrai apport de Docker, c'est de l'avoir rendu utilisable par n'importe quel développeur, avec un format d'image standard et quelques commandes simples, tapées dans le terminal.

L'analogie du conteneur maritime

Avant l'invention du conteneur maritime dans les années 1950, transporter des marchandises était un cauchemar logistique. Chaque cargaison avait sa forme, sa taille, son emballage. Les dockers devaient charger et décharger chaque produit individuellement. C'était lent, coûteux et fragile.

Le conteneur standardisé a tout changé. Peu importe ce qu'il y a dedans (des chaussures, du café, des voitures), l'extérieur est toujours le même. Les grues, les camions et les bateaux savent manipuler n'importe quel conteneur de la même façon.

Docker applique exactement ce principe au logiciel. Un conteneur Docker emballe une application avec tout ce dont elle a besoin pour fonctionner : le code, le langage, les bibliothèques, la configuration. Ce conteneur peut ensuite tourner à peu près n'importe où, sur le poste du développeur, en préproduction, en production ou chez n'importe quel hébergeur cloud, avec le même comportement. Ce qui reste en dehors du conteneur, la puissance de la machine ou les données réelles, continue bien sûr de différer d'un environnement à l'autre.

Conteneur vs machine virtuelle

Pour isoler des applications, l'outil historique, c'est la machine virtuelle (VM). Une VM simule un ordinateur complet, avec son propre système d'exploitation, sa propre mémoire et ses propres processus. C'est lourd. Démarrer une VM prend des minutes et consomme beaucoup de ressources.

Un conteneur est beaucoup plus léger. Il réutilise le système d'exploitation de la machine hôte et n'isole que ce qui est nécessaire. Il démarre en quelques secondes et consomme bien moins de ressources. On peut facilement faire tourner des dizaines de conteneurs sur une seule machine, là où quelques VM suffiraient à la saturer.

Cette légèreté suppose un système hôte de type Linux, puisque c'est son mécanisme d'isolation que Docker utilise. Sur Windows et sur Mac, Docker fait donc tourner en coulisses une petite machine virtuelle Linux dans laquelle vivent les conteneurs. Ça marche très bien, ça explique simplement pourquoi les postes de développement sous Mac ou Windows sont parfois plus lents que la production.

L'image : la recette du conteneur

Deux mots reviennent sans arrêt et méritent d'être distingués. L'image, c'est le modèle figé, une photo de l'application et de tout son environnement. Le conteneur, c'est une instance de cette image en train de tourner. Une seule image peut donner naissance à autant de conteneurs identiques qu'on veut, exactement comme une classe et ses objets.

La recette qui fabrique l'image est écrite dans un fichier appelé Dockerfile : "prends Linux, installe Python 3.12, copie mon code, installe les dépendances, lance le serveur". À partir de cette recette, Docker fabrique un conteneur identique à chaque fois, sur n'importe quelle machine.

Les images peuvent être partagées sur des registres publics comme Docker Hub. Il existe des images prêtes à l'emploi pour à peu près tout : bases de données, serveurs web, langages de programmation... Un développeur peut démarrer un environnement complet en une seule commande.

Une image de base est une dépendance comme une autre. On part du travail de quelqu'un d'autre, parfois plus maintenu depuis des années et truffé de failles connues, et on construit dessus. Choisir une image officielle et la mettre à jour régulièrement relève des mêmes réflexes que ceux du chapitre sur les frameworks et bibliothèques.

Le conteneur oublie tout

C'est la notion la plus importante du chapitre, et celle qui provoque le plus de malentendus. Un conteneur est jetable. Quand il s'arrête, tout ce qui a été écrit à l'intérieur disparaît, et le prochain repart de l'image, vierge. C'est voulu, c'est ce qui rend les conteneurs interchangeables.

Or une base de données, elle, doit survivre. Les commandes, les clients, les fichiers déposés par les utilisateurs ne vivent donc jamais dans le conteneur, mais dans un espace de stockage rattaché de l'extérieur, qui reste en place quand le conteneur est remplacé. On n'emballe pas les données avec l'application, on emballe l'application et on la branche sur les données.

Docker Compose : orchestrer plusieurs conteneurs

Une application moderne est rarement un seul programme. Elle est composée de plusieurs briques : un serveur web, une base de données, un système de cache, une file de messages...

Docker Compose permet de décrire tous ces conteneurs et leurs liens dans un seul fichier. Une commande suffit pour démarrer l'ensemble. C'est comme un chef d'orchestre qui lance tous les musiciens en même temps.

Pour les environnements de production à grande échelle, on utilise Kubernetes, un outil né chez Google en 2014 et depuis confié à une fondation, qui gère des centaines, voire des milliers de conteneurs répartis sur de nombreuses machines. Il s'occupe de la montée en charge, du redémarrage automatique des conteneurs qui plantent, et de la répartition intelligente des ressources.

C'est le mot que tu entendras le plus souvent, et il mérite une mise en garde. Kubernetes est un outil d'une complexité redoutable, qui demande des compétences rares et une équipe pour l'entretenir. Beaucoup d'entreprises l'adoptent parce que les grands le font, alors que trois conteneurs sur une machine ou une offre gérée par l'hébergeur cloud auraient largement suffi. Le chapitre sur le DevOps y revient.

Pourquoi Docker a tout changé

Docker a démocratisé une idée qui circulait déjà, celle de décrire l'infrastructure comme du code. L'environnement d'exécution n'est plus configuré manuellement sur chaque serveur, il est écrit dans des fichiers versionnés au même titre que l'application.

Les avantages sont considérables :

  • Reproductibilité : l'environnement de production est identique à celui du développeur. Fini le "ça marche sur ma machine".
  • Isolation : chaque application tourne dans son conteneur, avec ses propres dépendances. Deux applications qui ont besoin de versions différentes du même outil peuvent coexister sans conflit.
  • Rapidité : un nouveau développeur qui rejoint l'équipe peut lancer tout l'environnement en quelques minutes au lieu de passer une journée à installer et configurer chaque composant.

Pour toi, ça se traduit par deux bénéfices très concrets. Le premier, reproduire à l'identique le bug d'un client, puisque l'équipe peut relancer chez elle exactement la version qui tourne en production. Le second, disposer d'un environnement jetable par fonctionnalité, monté en quelques minutes pour te faire valider un écran avant la mise en ligne, et détruit juste après.

Ce que Docker ne fait pas

  • Ce n'est pas une sauvegarde : l'image conserve l'application, pas les données. Les sauvegardes de la base restent à organiser à côté.
  • Ce n'est pas une garantie de sécurité : un conteneur isole, il ne protège pas d'une image vérolée ni d'une application mal écrite.
  • Ce n'est pas gratuit : des images lourdes à fabriquer et à transférer à chaque livraison, un registre à héberger, et une couche de plus à comprendre quand quelque chose ne marche pas.

Aujourd'hui, Docker est devenu un outil incontournable. La quasi-totalité des déploiements cloud modernes utilisent des conteneurs.

PrécédentFrameworks et bibliothèques Tous les chapitres