Avec Docker, le Cloud Computing est-il sur le point de franchir un nouveau cap ?

La virtualisation des machines est le fondement du Cloud Computing tel que nous le connaissons aujourd’hui. Pourtant, il semble que les grands acteurs du Cloud public s’intéressent de plus en plus aux mécanismes de virtualisation à base de containers, ainsi qu’aux solutions permettant de les gérer plus les efficacement. Parmi celles-ci, le projet Open Source Docker semble recueillir la plus grande attention.
J’ai récemment eu l’occasion de participer à un projet Azure qui m’a offert l’occasion de me pencher sur le sujet. Voici donc une série d’articles qui je l’espère vous permettra d’accélérer votre découverte de cet environnement.
Docker : les fondamentaux
Mise en place de l’environnement Docker : Installation du moteur et du client Docker
Docker et la virtualisation par container sous Windows
Mise en place de l’environnement Docker : Provisioning d’un host Docker dans Azure
Utilisation de Docker
Clusters de containers Docker

Docker : les fondamentaux

Virtualisation par les containers LXC 

LXC est une technologie de virtualisation que l’on peut mettre en œuvre sur de multiples distributions Linux. Le principe consiste à reconstruire la vue qu’un processus a de son environnement d’exécution (et de lui donner l’illusion qu’il est le seul à s’exécuter sur la machine, avec une arborescence de fichiers limitée par le périmètre du container). Les containers sont isolés mais partagent l’OS et le cas échéant certaines librairies. Il en résulte un déploiement et un redémarrage plus rapide, moins d’overhead, ainsi qu’une grande facilité de migration.

image

Les containers Docker : exécution des applications

A l’origine, Docker se fonde sur les mécanismes de container LXC. Si le container d’application offre de multiples analogies avec le container qui a révolutionné le transfert maritime (capacité à empaqueter tout type d’application et de ses dépendances, exécution sur tout type d’environnement, isolation des dépendances, facilité de déplacement), Docker s’inspire directement de son homologue portuaire.
Le rôle de Docker est en effet de faciliter le chargement et le déchargement de ces containers et de contribuer à la construction d’un écosystème qui va pouvoir tirer le meilleur parti de ce nouveau mode d’échange. Docker étend le format LXC, afin de permettre d’empaqueter une application et ses dépendances au sein d’un container. La contribution la plus significative de Docker se matérialise donc dans les moyens qu’il met à disposition pour définir comment les containers et leur contenu est défini puis distribué. Grâce à l’automatisation de la manipulation des containers, Docker offre la possibilité de déployer des applications avec des caractéristiques d'isolement similaires à celles d’applications s'exécutant dans des machines virtuelles tout en évitant les contraintes liées au chargement en mémoire du système d'exploitation et de ses services complémentaires.

Un container Docker se présente comme un répertoire contenant les pré-requis pour l’exécution d’une application. Il est constitué d'un système d'exploitation, des fichiers ajoutés par l'utilisateur et des métadonnées. Un container peut être lancé, arrêté, interrogé pour connaitre son statut, supervisé, déplacé, supprimé. Chaque container est isolé des autres containers qui peuvent s’exécuter simultanément sur le même système.
Ces containers sont créés à partir d’images Docker.

Les images Docker : génération des modèles d’applications

Docker offre la possibilité pour les développeurs de créer, personnaliser et composer des images d'application accessibles en lecture seule qui pourront être ultérieurement déployée sur de multiples hôtes Docker. Docker offre les commandes permettant de construire de nouvelles images application préconfigurée (ce qui inclut l’ensemble de ces dépendances logicielles) ou de mettre à jour les images existantes.
Par exemple, Docker permet très simplement de mettre à disposition un modèle d’application Web Node.js offrant des fonctions de realtime grâce à Socket.io et interagissant avec une base MongoDB.

      
Chaque image commence par une image de base, par exemple, Ubuntu ou plus « avancée » comme nodejs installée sur Ubuntu. Chaque image est ensuite constituée d'une série de couches baptisées « layers ». Docker utilise des regroupement de systèmes de fichiers distincts baptisées « branches » pour combiner ces couches en une seule image donnant une vue cohérente de l’ensemble. Lorsque l’on modifie une image de Docker, par exemple, pour mettre à jour une application vers une nouvelle version, un nouveau « layer » est généré. Ce processus de mise à jour est extrêmement efficace et se traduit par une distribution simple et rapide. En effet, seul ce nouveau « layer » sera distribué lors d’une prochaine mise à jour de l’image, au lieu d’un remplacement intégral de l'image comme le nécessiterait une machine virtuelle.
L’image indique à Docker ce que le container contient, quel processus s'exécute lorsque le container est lancé et une variété d'autres données de configuration. Lors de l'exécution de Docker le container ajoute une couche de lecture / écriture sur le dessus de l'image.

L'image de base fournit l’environnement minimal pour l’OS (système de fichiers, bibliothèques et autres….). Puis les « layers » sont ajoutés pour les packages d'application ou les informations de configuration. Chaque « layer » est identifié de manière unique et stocké sous forme d'une archive « tar » avec le contenu et des métadonnées qui indiquent, entre autres, la liste des « layers » sous-jacents... Lorsqu'une « image » est stockée dans le référentiel, elle reçoit un nom et éventuellement une étiquette (« tag ») afin qu'elle puisse être récupérée sur demande.
Les images de docker sont donc construites à partir d’images de base à l'aide d'un jeu d’instructions (lancer l’installation d’un framework, ajouter un module, ajouter des fichiers à l’application, lancer un processus) permettant de décrire l’image cible, chaque instruction se traduisant par un nouveau « layer » sur cette image. Ces instructions peuvent être exécutées manuellement ou enregistrées dans un fichier Dockerfile, qui sera le point d’entrée de la commande « build » de Docker pour générer l’image finale. Docker impressionne par la facilité avec laquelle il permet de créer un environnement d’exécution pour une application.
Docker permet alors de télécharger ces images vers des référentiels.

Les référentiels Docker : la publication et distribution des images

Les référentiels d’images peuvent être privés ou publics. Ils permettent de stocker les images, de les nommer et de les mettre à disposition pour un téléchargement afin qu’elles puissent être réutilisées. Parce que l'application a été testée dans un container, le développeur est assuré de la présence des prérequis de configuration qui en garantissent l’exécution, indépendamment des autres services qui pourraient cohabiter sur le même hôte.
Le référentiel public, le Docker Hub offre un très large éventail de services et d'images existantes :
• La « registry », qui est un système de stockage pour les images de containers
• Le « public index », qui permet de référencer les images publiques avec un système d’attribution d’étoiles pour le « ranking »
• « Automated builds », qui permet de lier un dépôt de code GitHub ou Bitbucket, et créer automatiquement des images Docker à chaque commit, afin que ces images soient toujours à jour par rapport au code.
Le référentiel Docker Hub est également exposé via une API REST.

Topologie de l’environnement

L’environnement Docker est fondé sur une architecture client-serveur. Il n’y a pas d’interaction directe avec le serveur, toutes les requêtes sont à l’initiative du client. Le client Docker communique avec un service Docker, le « Docker Engine » qui assure la génération et la publication des images ainsi que leur exécution au sein de containers. Les composants correspondants (le client Docker et le démon à l’écoute de ses requêtes) communiquent via des sockets ou via une API REST. Toutes les fonctions de Docker sont donc exposées via cette API, ou via un outil en ligne de commande. Le « Docker Engine », peut être installé sur un serveur Linux et le transformer ainsi en hôte Docker.

image
Dans le prochain article nous étudierons les multiples façons de mettre en place cet environnement.