Machines virtuelles et Docker : une maison lourde et une tente légère

« Installe une machine virtuelle Linux et recrée exactement le même environnement. »

Trois mois après mon arrivée dans l’entreprise, l’ambiance au bureau était étrange. Notre seul senior venait d’être officiellement affecté à un autre projet et était tellement occupé à faire ses cartons qu’il n’avait même pas le temps de penser à la transmission. Quant au chef d’équipe, cela faisait longtemps qu’il avait quitté le terrain du développement concret et il était assez éloigné des tendances techniques récentes.

Un jour, le chef d’équipe m’a appelé. « Quand ton senior sera parti, il n’y aura plus que toi pour gérer le serveur. Même si le serveur tombe, tu dois pouvoir le remettre en état tout seul. Installe Linux en machine virtuelle, VM, sur ton portable de développement actuel, Windows, et reconstruis exactement le même environnement que le serveur de production. »

C’est là que ma galère a commencé. J’ai installé VMware, téléchargé l’ISO Ubuntu, et rien que l’installation m’a pris une demi-journée. J’ai fouillé dans le wiki de l’entreprise pour installer Java, Node.js et PostgreSQL. Je me suis dit : « Le plus récent sera forcément mieux », et j’ai installé Java 17, avant de découvrir que le code legacy reposait en fait sur Java 8 et ne compilait même pas. Il a fallu tout supprimer et tout réinstaller. À chaque fois que je modifiais une seule ligne de code, je devais lancer mvn build, déplacer le fichier jar dans la VM puis l’exécuter là-bas. C’était une vraie torture.

Puis une question m’est soudain venue. « Attends une seconde. La dernière fois qu’on a déployé sur le serveur de production, ça ne s’est pas terminé simplement avec une seule commande docker service update ? »

Ma machine virtuelle locale était aussi lourde et demandait une montagne de configuration. Alors qu’est-ce que c’était exactement, ce ‘Docker’ du serveur de production, pour permettre une mise à jour avec une simple ligne de commande ?

Docker est la manière la plus légère de déplacer un environnement entier.

La solution lourde : la machine virtuelle

La méthode demandée par mon chef, c’est-à-dire installer Linux au-dessus de Windows, correspond exactement à ce qu’est une machine virtuelle, VM. C’est comme construire une ‘maison virtuelle’, un guest OS, entière au-dessus d’un ordinateur physique, l’hôte.

  • Principe : on fait tourner plusieurs OS sur un seul ordinateur. (Linux sur Windows, puis encore Linux par-dessus…)
  • Problème : pour construire la maison, il faut tout bâtir à neuf : les piliers, les murs et même les toilettes (le noyau).
    • Pour faire tourner une seule application, il faut installer un OS complet de plusieurs gigaoctets.
    • Le démarrage prend une éternité. (C’est pour ça que mon portable était devenu si lent.)
    • Les ressources sont mal utilisées. (Même sans rien faire, l’OS consomme de la mémoire rien que pour rester en marche.)

Au final, une VM isole bien l’environnement, certes, mais pour le développement ou le déploiement, c’était tout simplement trop lourd et trop lent pour être manipulé à chaque fois.

La révolution légère : Docker

C’est ainsi qu’est apparu Docker, autrement dit la technologie des conteneurs. Docker ne construit pas une maison entière comme le fait une VM. À la place, il plante une tente.

  • Principe : on partage la cour, c’est-à-dire le noyau, d’une maison déjà construite, l’OS hôte sous Linux. On se contente d’y planter des tentes isolées : les conteneurs.
  • Caractéristiques :
    • Il partage l’OS, plus précisément le noyau : la tente ne contient pas d’OS lourd. Seulement mon application et ses bibliothèques.
    • Il est léger : sa taille se compte en mégaoctets (Mo).
    • Il est rapide : un démarrage ? Ça n’existe pas. Il s’allume à la vitesse du lancement d’un simple processus, en quelques millisecondes.

La commande update que j’ai lancée sur le serveur de production ne réinstallait pas un système d’exploitation lourd. Elle se contentait de « démonter l’ancienne tente puis d’en remonter une nouvelle contenant la nouvelle version du code ». Il était donc inévitable que cela se termine presque instantanément.

[Code Verification] Docker est-il vraiment si léger ?

Ne nous contentons pas de dire que Docker est léger, vérifions-le réellement. Si l’objectif est d’exécuter un environnement Linux, Ubuntu, alors la différence entre une VM et Docker est flagrante.

  1. Lancer Ubuntu dans une VM : téléchargement du fichier ISO (2 Go) -> installation (20 minutes) -> démarrage (1 minute).
  2. Lancer Ubuntu avec Docker :
# Lancer Ubuntu avec la commande Docker (telechargement automatique si limage manque)
$ docker run -it ubuntu:latest /bin/bash

Résultat :

  • Téléchargement : environ 30 Mo (une image minimale qui ne garde que l’essentiel d’Ubuntu)
  • Temps d’exécution : environ 0,5 seconde

Dès que j’ai appuyé sur Entrée, j’étais déjà dans un environnement Ubuntu. Si c’est possible, c’est parce qu’un conteneur Docker n’est pas un véritable système d’exploitation. Ce n’est qu’« un espace isolé qui emprunte le noyau du système hôte, mon ordinateur, tout en faisant semblant d’être un OS séparé ».

Conseil pratique : la vraie raison d’utiliser Docker

Depuis que nous avons introduit Docker dans notre travail, ma vie a complètement changé.

  1. Fini les « Configurez votre environnement » : autrefois, quand un nouvel employé arrivait, on lui remettait un document de dix pages A4 en lui disant « Installez Java, configurez les variables d’environnement, installez la base de données… ». Aujourd’hui, on lui dit simplement : « Installez Docker et tapez docker-compose up. »
  2. Fin de l’enfer des versions : et si le projet A doit utiliser Java 8 et le projet B Java 17 ? Si l’on installe les deux en local, ils entrent en conflit et tout s’emmêle. Avec Docker, on met Java 8 dans le conteneur A et Java 17 dans le conteneur B, et on peut les lancer en même temps sans le moindre problème. Tout simplement parce qu’ils sont parfaitement ‘isolés’ les uns des autres : c’est l’isolation.

En conclusion : on ne livre plus un exécutable, mais un environnement

L’arrivée de Docker a changé le paradigme du développement. Nous n’envoyons plus uniquement le code source, .java, sur le serveur. Nous figeons aussi la configuration de l’OS, les bibliothèques et les variables d’environnement nécessaires au code dans une ‘image’, puis nous envoyons le tout.

Alors, comment cette ‘image Docker’ presque magique est-elle réellement fabriquée ? Est-ce juste un fichier compressé ? De manière surprenante, on dit qu’une image Docker est empilée en plusieurs couches, comme un gâteau.

La prochaine fois, examinons le secret de l’efficacité de Docker : les images et leur structure en couches.

Laisser un commentaire