Docker constitue une tech­no­lo­gie dédiée à la vir­tua­li­sa­tion basées sur des con­te­neurs d’ap­pli­ca­tions logiciel. L’approche grand public basée sur les con­te­neurs de Docker a changé le visage du dé­ve­lop­pe­ment d’ap­pli­ca­tions ces dernières années. Elle a affecté chacune des dif­fé­rentes zones du dé­ve­lop­pe­ment, y compris la manière dont les ap­pli­ca­tions et les com­po­sants sont dé­ve­lop­pés et dont les services logiciel sont dis­tri­bués, et a déplacé ces derniers du dé­ve­lop­pe­ment à la pro­duc­tion. Avec Docker, tous ces processus sont exécutés d’une manière dif­fé­rente de celle dont ils l’étaient au­pa­ra­vant.

Mais les processus de dé­ve­lop­pe­ment ne sont pas les seuls à avoir changé : c’est aussi le cas de l’ar­chi­tec­ture lo­gi­cielle. Elle a glissé de solutions générales mo­no­li­thiques vers des clusters de « mi­cro­ser­vices » associés légers. Ceci a, en retour, rendu dans leur ensemble les systèmes en résultant plus complexes. Ces dernières années, des logiciels tels que Ku­ber­netes se sont imposés comme des leaders dans la gestion d’ap­pli­ca­tions multi-con­te­neurs.

Le dé­ve­lop­pe­ment de la vir­tua­li­sa­tion basée sur les con­te­neurs est loin d’être achevé, ce dernier restant dès lors un champ d’ex­pé­ri­men­ta­tion in­té­res­sant. Dans cet article, nous vous ex­pli­quons comment Docker fonc­tionne en tant que tech­no­lo­gie sous-jacente. Par ailleurs, nous exa­mi­ne­rons les raisons qui ont conduit au dé­ve­lop­pe­ment de Docker.

Note

Le nom « Docker » recouvre plusieurs sens. Il est utilisé en tant que synonyme du logiciel lui-même, pour désigner le projet open source sur lequel il est basé, et une compagnie amé­ri­caine qui gère divers produits et services à titre com­mer­cial.

Docker : his­to­rique rapide

Le logiciel publié à l’origine sous le nom « Docker » fut développé sur la base de la tech­no­lo­gie Linux Container (LXC). LXC fut ensuite remplacée par le lib­con­tai­ner de Docker. De nouveaux com­po­sants logiciel ont été ajoutés alors que Docker a continué à croître et à devenir le standard pour la vir­tua­li­sa­tion basée sur les con­te­neurs. Con­tai­nerD a notamment émergé du dé­ve­lop­pe­ment de Docker en tant que moteur d’exécution de conteneur avec l’im­plé­men­ta­tion standard runC. Aujourd’hui, ces projets sont gérés par la Cloud Native Computing Foun­da­tion (CNCF) et l’Open Container Ini­tia­tive (OCI).

Outre l’équipe consacrée à Docker, des en­tre­prises leader dans le monde de la tech telles que Cisco, Google, Huawei, IBM, Microsoft, ou encore Red Hat sont im­pli­quées dans le dé­ve­lop­pe­ment de Docker et de tech­no­lo­gies connexes. Parmi les évo­lu­tions les plus récentes, on notera le fait que Windows est désormais également utilisé en tant qu’en­vi­ron­ne­ment natif pour les con­te­neurs Docker, en plus du noyau Linux. Ci-dessous, voici quelques-uns des jalons majeurs dans l’his­to­rique de l’évolution de Docker :

Années Étapes-clés dans l’évolution de Docker
2007 La tech­no­lo­gie cgroup est intégrée au noyau Linux
2008 Sortie de LXC ; il s’appuie sur les espaces de nom de cgroups et Linux, comme Docker le fera par la suite
2013 Sortie de Docker comme logiciel open source
2014 Docker est dis­po­nible sur Amazon EC2
2015 Sortie de Ku­ber­netes
2016 Docker est dis­po­nible sous Windows 10 via Hyper-V
2019 Docker est dis­po­nible sous Windows Home via WSL2
Conseil

À la fin de cet article, nous entrerons plus en détails sur ce qui a motivé le dé­ve­lop­pe­ment de Docker et de tech­no­lo­gies de vir­tua­li­sa­tion si­mi­laires.

Qu’est-ce que Docker ?

La fonc­tion­na­lité centrale de Docker est la vir­tua­li­sa­tion d’ap­pli­ca­tions basée sur les con­te­neurs. Cela contraste avec la vir­tua­li­sa­tion via des machines vir­tuelles (VM). Avec Docker, le code de l’ap­pli­ca­tion, qui comprend toutes les dé­pen­dances, est empaqueté à l’intérieur d’une « image ». Le logiciel Docker exécute l’ap­pli­ca­tion em­pa­que­tée dans un conteneur Docker. Les images peuvent être déplacées d’un système à l’autre et être exécutées sur tout système com­pa­tible avec Docker.

Citation

"Con­tai­ners are a stan­dar­di­zed unit of software that allows de­ve­lo­pers to isolate their app from its en­vi­ron­ment […]“ – Citation d’un dé­ve­lop­peur de Docker source: https://www.Docker.com/why-Docker

« Les con­te­neurs cons­ti­tuent des unités stan­dar­di­sées de software qui per­met­tent à des dé­ve­lop­peurs d’isoler leur appli de son en­vi­ron­ne­ment […] » – (Tra­duc­tion : IONOS)

Comme c’est le cas avec le dé­ploie­ment d’une machine virtuelle (VM), une des premières préoc­cu­pa­tions des con­te­neurs Docker est d’isoler l’ap­pli­ca­tion en cours d’exécution. À la dif­fé­rence des VM, néanmoins, un système d’ex­ploi­ta­tion entier n’est pas vir­tua­lisé. À la place, Docker alloue certaines res­sources issues du système d’ex­ploi­ta­tion et du matériel à chaque conteneur : on peut créer et diriger en parallèle autant de con­te­neurs qu’on veut à partir d’une image Docker. C’est ainsi que les services Cloud ex­ten­sibles sont mis en place.

Bien que nous parlions de Docker comme d’une simple partie d’un logiciel, il s’agit en réalité de multiples com­po­sants de logiciels qui com­mu­ni­quent via l’API Docker Engine. Par ailleurs, une poignée d’objets Docker spéciaux sont utilisés tels que les images sus­men­tion­nées et les con­te­neurs. Des workflows spé­ci­fiques à Docker sont cons­ti­tués des com­po­sants logiciels et des objets Docker. Jetons un œil à la manière dont ils in­te­ra­gis­sent en détails.

Logiciel Docker

La base du logiciel Docker est le Docker-Engine. Ce dernier est prin­ci­pa­le­ment utilisé pour gérer et contrôler les con­te­neurs et leurs images sous-jacentes. Des outils spé­ci­fiques sont utilisés pour d’autres fonc­tion­na­li­tés. Ceux-ci sont prin­ci­pa­le­ment requis pour gérer des ap­pli­ca­tions cons­ti­tuées de groupes de con­te­neurs.

Docker Engine

Docker Engine est exécuté sur un système local ou un serveur et est constitué de deux com­po­sants :

  1. Le Docker Daemon (Dockerd) : ce dernier est cons­tam­ment exécuté en arrière-plan et à l’affût de requêtes de l’API Docker Engine. Dockerd répond aux commandes ad hoc pour gérer les con­te­neurs Docker et d’autres objets Docker.
  2. Le Docker Client (Docker) : il s’agit d’un programme de ligne de commande. Le Docker Client est utilisé pour contrôler le Docker Engine et fournit des commandes pour créer et dé­ve­lop­per des con­te­neurs Docker, ainsi que pour créer, obtenir et ver­sion­ner des images Docker.

L’API Docker Engine

L’API Docker Engine est une API REST. Elle com­mu­nique avec le Docker Daemon. Des « kits de dé­ve­lop­pe­ment logiciel » (SKD pour Software De­ve­lop­ment Kit) officiels pour Go et Python sont dis­po­nibles pour intégrer l’API Docker Engine dans des projets de logiciels. Des bi­blio­thèques si­mi­laires existent également pour plus d’une douzaine d’autres langages de pro­gram­ma­tion. Vous pouvez accéder à l’API avec la ligne de commande à l’aide de la commande Docker. Par ailleurs, vous pouvez accéder à l’API di­rec­te­ment à l’aide de cURL ou d’outils si­mi­laires.

Outils Docker

Lorsque vous avez recours à des machines virtuelle, vous utilisez souvent des systèmes qui con­sis­tent en plusieurs com­po­sants logiciels. Par contraste, la vir­tua­li­sa­tion en con­te­neurs à l’aide de Docker favorise les clusters de mi­cro­ser­vices librement associés. Ces derniers sont adaptés pour les solutions Cloud dis­tri­buées qui offrent un haut degré de mo­du­la­rité et une grande dis­po­ni­bi­lité. Quoi qu’il en soit, ces types de systèmes de­vien­nent ra­pi­de­ment très complexes. Pour gérer des ap­pli­ca­tions con­te­neu­ri­sées de manière efficace, vous avez recours à des outils logiciels spé­ci­fiques appelés « or­ches­tra­teurs ».

Docker Swarm et Docker Compose sont deux outils Docker officiels qui sont dis­po­nibles pour or­ches­trer les clusters de con­te­neurs. La commande « Docker swarm » peut être utilisée pour combiner plusieurs Docker Engines en un seul engin virtuel. On peut ensuite faire fonc­tion­ner les engins in­di­vi­duels à travers de multiples systèmes et in­fras­truc­tures. La commande « Docker Compose » est utilisée pour créer des ap­pli­ca­tions multi-con­te­neurs, que l’on appelle également des « stacks ».

L’or­ches­tra­teur Ku­ber­netes, développé à l’origine par Google, est plus er­go­no­mique que Swarm et Compose. Il s’est imposé comme le standard dans son domaine et est très largement utilisé au sein du secteur. Les en­tre­prises d’hé­ber­ge­ment et les four­nis­seurs de solutions « Software as a Service » (SaaS) et « Platform as a Service » (PaaS) utilisent de plus en plus Ku­ber­netes à titre d’in­fras­truc­ture sous-jacente.

Les objets Docker

Les workflows dans l’éco­sys­tème Docker cons­ti­tuent un résultat de la manière dont les objets Docker in­te­ra­gis­sent les uns avec les autres. Ils sont gérés en com­mu­ni­quant avec l’API Docker Engine. Jetons un œil à chaque type d’objet en détails.

Image Docker

Une image Docker est un modèle en lecture seule pour créer un ou plusieurs con­te­neurs iden­tiques. Les images Docker cons­ti­tuent de facto les racines du système ; elles sont utilisées pour mettre en paquets et livrer les ap­pli­ca­tions.

Divers dépôts sont utilisés pour partager les images Docker. Il existe aussi bien des dépôts publics que privés. Lorsque nous écrivons ces lignes, plus de cinq millions d’images sont dis­po­nibles en té­lé­char­ge­ment sur le célèbre « Docker Hub ». Les commandes Docker « Docker pull » et « Docker push » sont utilisées pour té­lé­char­ger une image depuis un dépôt et la partager à cet endroit.

Les images Docker sont cons­truites par couches. Chaque couche re­pré­sente un chan­ge­ment spé­ci­fique apporté à l’image. Ceci a pour résultat un ver­sion­nage continu des images, lequel permet un retour à un état antérieur. Une image existante peut être utilisée à titre de base pour créer une nouvelle image.

Do­cker­file

Un Do­cker­file est un fichier texte qui décrit la structure d’une image Docker. Un Do­cker­file est similaire à un script de trai­te­ment par lots : le fichier contient des commandes qui décrivent une image. Lorsque vous exécutez un Do­cker­file, les commandes sont traitées l’une après l’autre. Chaque commande crée une nouvelle couche dans l’image Docker. Vous pouvez donc également voir un Do­cker­file comme une sorte de recette utilisée comme base pour créer une image.

Conteneur Docker

Passons main­te­nant au concept central de l’univers Docker : les con­te­neurs Docker. Tandis que, d’un côté, une image Docker constitue un modèle inerte, de l’autre, un conteneur Docker re­pré­sente une instance active et en cours d’exécution d’une image. Une image Docker existe lo­ca­le­ment sous la forme d’une copie unique et ne prend qu’une faible quantité d’espace de stockage. Par contraste, de multiples con­te­neurs Docker peuvent être créés depuis la même image et être exécutés en parallèle.

Chaque conteneur Docker consomme une certaine part des res­sources du système lors de son exécution, comme le pro­ces­seur, la RAM, les in­ter­faces réseau, etc. Un conteneur Docker peut être créé, lancé, in­ter­rompu, et détruit. Vous pouvez également sau­ve­gar­der l’état d’un conteneur en cours d’exécution en tant que nouvelle image.

Volume Docker

Comme nous l’avons vu, vous créez un conteneur Docker exé­cu­table à partir d’une image non-exé­cu­table. Mais qu’en est-il des données qui sont utilisées à l’intérieur du conteneur et ont besoin d’être main­te­nues au-delà de sa durée de vie ? C’est dans de tels cas qu’on aura recours aux volumes Docker. Un volume Docker existe en-dehors d’un conteneur spé­ci­fique. Dès lors, plusieurs con­te­neurs peuvent partager un même volume. Les données contenues dans le volume sont stockées sur le système de fichiers de l’hôte. Cela signifie qu’un volume Docker est com­pa­rable à un dossier partagé sur une machine virtuelle.

Comment Docker fonc­tionne-t-il ?

Le principe de fonc­tion­ne­ment de base de Docker est similaire à celui de LXC, la tech­no­lo­gie de vir­tua­li­sa­tion dé­ve­lop­pée pré­cé­dem­ment : tous deux s’appuient sur le noyau Linux et exécutent une vir­tua­li­sa­tion basée sur des con­te­neurs. Docker comme LXC combinent deux buts con­tra­dic­toires :

  1. Des con­te­neurs en cours d’exécution partagent le même noyau Linux, ce qui les rend plus léger que des machines vir­tuelles.
  2. Des con­te­neurs en cours d’exécution sont isolés les uns des autres et ont uni­que­ment accès à une quantité limitée de res­sources système.

Docker et LXC ont recours aux « espaces de nom du noyau » et aux « groupes de contrôle » pour atteindre ces buts. Jetons un œil à la manière dont cela fonc­tionne en détails.

Le noyau Linux

Le noyau Linux constitue le composant central du système d’ex­ploi­ta­tion open source GNU/Linux. Le noyau gère le hardware et contrôle les processus. Lorsque l’on exécute Docker en-dehors de Linux, un hy­per­vi­seur ou une machine virtuelle est né­ces­saire pour apporter la fonc­tion­na­lité du noyau Linux. Sur macOS, xhyve, un dérivé de l’hy­per­vi­seur BSD hy­per­vi­sor bhyve, est employé. Sur Windows 10, Docker utilise l’hy­per­vi­seur Hyper-V.

Les espaces de nom du noyau

Les espaces de nom cons­ti­tuent une des ca­rac­té­ris­tiques du noyau Linux. Ils com­par­ti­men­tent les res­sources du noyau et s’assurent ainsi que les processus restent séparés les uns des autres. Un processus d’espace de nom peut uni­que­ment voir les res­sources de noyau du même espace de nom. Voici un aperçu de l’espace de nom utilisé dans Docker :

Espace de nom Des­crip­tion Ex­pli­ca­tion
UTS Iden­ti­fi­ca­tion Système Assigne des con­te­neurs à leurs propres hôtes et noms de domaine
PID ID de processus Chaque conteneur utilise son propre espace de nom pour les ID de processus ; les PID issus d’autres con­te­neurs ne sont pas visibles ; par con­sé­quent, deux processus dans des con­te­neurs dif­fé­rents peuvent avoir recours au même PID sans conflit.
IPC Com­mu­ni­ca­tion inter-processus Les espaces de nom IPC isolent les processus dans un seul conteneur de sorte qu’ils ne puissent com­mu­ni­quer avec les processus dans d’autres con­te­neurs.
NET Res­sources réseau Assigne des res­sources réseau séparées telles que des adresses IP ou des tableau de routage à un conteneur
MNT Points de montage du système fichier Restreint le système fichier de l’hôte à une section étroi­te­ment définie du point de vue du conteneur

Groupes de contrôle

Les groupes de contrôle, dont l’abré­via­tion courante est cgroups, sont utilisés pour organiser les processus Linux de manière hié­rar­chique. Un processus (ou groupe de processus) se voit allouer un nombre limité de res­sources système. Ceci comprend la RAM, les cœurs du pro­ces­seur, le stockage de masse et les appareils réseaux (virtuels). Tandis que les espaces de nom isolent les processus les uns des autres, les groupes de contrôle limitent l’accès aux res­sources système. Ceci garantit le fait que le système, dans son ensemble, reste en état de marche lorsqu’il fait fonc­tion­ner de multiples con­te­neurs.

Quels sont les avantages de Docker ?

Jetons un œil à l’histoire du dé­ve­lop­pe­ment in­for­ma­tique en vue de com­prendre les bénéfices apportés par Docker. Comment les logiciels étaient-ils dé­ve­lop­pés, livrés et exécutés au­pa­ra­vant et comment le sont-ils aujourd’hui ? Quels aspects du processus ont connu des chan­ge­ments radicaux ? Le logiciel est le pendant du matériel, l’or­di­na­teur physique. Sans le logiciel, l’or­di­na­teur constitue juste un bout de plastique et de métal. Alors que le matériel est fixe et ina­mo­vible, le logiciel peut être réinventé et per­son­na­lisé. C’est de l’in­te­rac­tion de ces deux niveaux que résulte cet ex­traor­di­naire monde digital.

Le logiciel sur une machine physique

Tra­di­tion­nel­le­ment, le logiciel est apparu pour être exécuté sur une machine physique. Mais on se heurte ra­pi­de­ment à un mur lorsque nous suivons cette voie. Un logiciel peut uni­que­ment être exécuté sur certaines machines, par exemple, car il a besoin d’un certain type de pro­ces­seur.

Par ailleurs, les logiciels les plus complexes ne sont en général pas exécutés de manière com­plè­te­ment autonome, mais sont intégrés au sein d’un éco­sys­tème logiciel. Ces derniers com­pren­nent un système d’ex­ploi­ta­tion, des bi­blio­thèques, et des dé­pen­dances. La bonne version de tous ces com­po­sants doit être dis­po­nible pour leur permettre d’interagir cor­rec­te­ment. Une con­fi­gu­ra­tion entre également en jeu, laquelle décrit de quelle manière les com­po­sants in­di­vi­duels sont liés les uns aux autres.

Si vous souhaitez exécuter plusieurs ap­pli­ca­tions sur une seule et même machine en parallèle, des conflits de versions émer­ge­ront sans tarder. Il se peut qu’une ap­pli­ca­tion nécessite une version d’un composant qui se trouve être in­com­pa­tible avec une autre ap­pli­ca­tion. Dans le pire des cas, chaque ap­pli­ca­tion devrait être exécutée sur sa propre machine physique. Ce qui est vrai est le fait que les machines physiques sont chères et ne peuvent pas s’adapter fa­ci­le­ment à la demande. Dès lors, si les besoins en res­sources d’une ap­pli­ca­tion croissent, il pourra être né­ces­saire de migrer cette dernière vers une nouvelle machine physique.

Le fait qu’un logiciel en cours de dé­ve­lop­pe­ment soit utilisé dans dif­fé­rents en­vi­ron­ne­ments soulève un autre problème. Un dé­ve­lop­peur écrit du code sur le système local et l’y exécute à titre de test. L’ap­pli­ca­tion passe par dif­fé­rents stades de test avant de passer en phase de pro­duc­tion, y compris un test d’en­vi­ron­ne­ment pour la cer­ti­fi­ca­tion de qualité ou un en­vi­ron­ne­ment de si­mu­la­tion pour être testé par l’équipe produit.

Les dif­fé­rents en­vi­ron­ne­ments existent souvent sur dif­fé­rentes machines physiques. Il existe presque toujours des dif­fé­rences dans les systèmes d’ex­ploi­ta­tion, les bi­blio­thèques, et les versions de con­fi­gu­ra­tion. Comment peut-on toutes les ré­con­ci­lier ? Car, si tous les en­vi­ron­ne­ments sont dif­fé­rents les uns des autres, les tests n’ont plus aucun sens. Par ailleurs, un système doit être remplacé en cas d’échec. Comment peut-on garantir la com­pa­ti­bi­lité ? Il n’est pas aisé de gérer ces problèmes sur des machines physiques.

Les machines vir­tuelles : un pas dans la bonne direction

La po­pu­la­rité des machines vir­tuelles (VM) découle des problèmes décrits avec l’uti­li­sa­tion des machines physiques. L’idée de base est d’intégrer une couche entre le matériel et le système d’ex­ploi­ta­tion ou les systèmes d’ex­ploi­ta­tion hôte et invité. Une VM découple l’en­vi­ron­ne­ment des ap­pli­ca­tions du matériel sous-jacent. La com­bi­nai­son spé­ci­fique d’un système d’ex­ploi­ta­tion, d’une ap­pli­ca­tion, de bi­blio­thèques, et d’une con­fi­gu­ra­tion peut être re­pro­duite depuis une image. Outre le fait d’isoler com­plè­te­ment une ap­pli­ca­tion, ceci permet aux dé­ve­lop­peurs de grouper plusieurs ap­pli­ca­tions dans une « appliance ».

Les images VM peuvent être déplacées entre les machines physiques, et de multiples système d’ex­ploi­ta­tion peuvent être exécutés en parallèle. Ceci garantit la sca­la­bi­lité de l’ap­pli­ca­tion. Quoi qu’il en soit, la vir­tua­li­sa­tion du système d’ex­ploi­ta­tion mobilise des res­sources im­por­tantes et est excessive pour de simples cas d’usage.

Les avantages de la vir­tua­li­sa­tion basée sur les con­te­neurs avec Docker

Les images utilisées dans la vir­tua­li­sa­tion basée sur les con­te­neurs n’ont pas besoin d’un système d’ex­ploi­ta­tion. La vir­tua­li­sa­tion basée sur les con­te­neurs est plus légère et apporte à peu de choses près une isolation aussi élevée que les VM. Une image conteneur combine le code d’une ap­pli­ca­tion avec toutes les dé­pen­dances requises et la con­fi­gu­ra­tion. Les images sont trans­fé­rables d’un système à l’autre, et les con­te­neurs dé­ve­lop­pées à partir de ces dernières peuvent être re­pro­duits. Les con­te­neurs peuvent être utilisés dans divers en­vi­ron­ne­ments, tels que le dé­ve­lop­pe­ment, la pro­duc­tion, le test et la si­mu­la­tion. Le contrôle de version des images et couches fournit également son lot de mo­du­la­rité.

Résumons donc les avantages-clés de la vir­tua­li­sa­tion basée sur Docker des ap­pli­ca­tions, par op­po­si­tion à l’uti­li­sa­tion d’une VM. Un conteneur Docker :

  • Ne contient pas son propre système d’ex­ploi­ta­tion et matériel simulé
  • Partage un même noyau de systèmes d’ex­ploi­ta­tion avec d’autres con­te­neurs hébergés sur le même système
  • Est léger et compact en termes d’uti­li­sa­tion des res­sources comparé à une ap­pli­ca­tion basée sur une VM
  • Se lance plus vite qu’une machine virtuelle
  • peut être utilisé en parallèle dans plusieurs instances de la même image
  • Peut être utilisé en même temps que d’autres services basés sur les con­te­neurs via l’or­ches­tra­tion
  • Est par­fai­te­ment adapté au dé­ve­lop­pe­ment en local
Aller au menu principal