Qu'est ce que Docker ? Pourquoi utiliser des containers ?

Publié le

Docker va permettre de gérer des containers. Un container est un moyen très utile de regrouper un programme ainsi que l'ensemble de ses dépendances.

Dans le monde réel, un container est facile à transporter : il a des dimensions standardisées, il peut être tracté par un camion ou chargé sur un bateau porte-container.

Dans le monde informatique aussi, un container est standardisé. On le crée à partir d'une image au format OCI (Open Container Initiative), et c'est très facile à transporter. On peut stocker l'image sous forme d'archive, ou plus couramment dans un annuaire centralisé qu'on appelle un container registry. On peut pousser l'image vers ce registry, ou la récupérer depuis ce même registry.

Par abus de language, on entend souvent parler d'image Docker ou de container Docker, mais en vérité, Docker n'est pas le seul outil à permettre la gestion de containers. Il en existe actuellement d'autres qui sont équivalents et compatibles. Par contre, il est vrai que c'est probablement Docker qui a popularisé les containers sous Linux.

Quelle est la différence entre un container et une machine virtuelle ?

Une machine virtuelle (VM pour Virtual Machine) est assez lourde à mettre en œuvre par rapport à un container :

  • dans une VM, on exécute un système d'exploitation complet.
  • on émule du vrai matériel, ou on partage du matériel physique de l'hôte entre les VMs.

**L'isolation de la partie logicielle **se fait à la fois **sur le système d'exploitation **exécuté par la VM, et sur les applications.

Il existe deux types d'hyperviseurs :

  • les hyperviseurs de type II, sont les plus utilisés par le grand publique. Ces solutions fonctionnent en espace utilisateur, comme n'importe quel autre programme. Ce n'est pas ce qu'il y a de plus performant. Parmi ces hyperviseurs, on retrouve des outils comme VirtualBox, VMWare Workstation ou VMWare Fusion, Parallels, etc.
  • les hyperviseurs de type I embarquent en général leur propre système d'exploitation. Un des plus connus est VMWare vSphere (technologie propriétaire). Une autre solution libre et répandue se base sur le noyau Linux : c'est kvm (avec éventuellement libvirt pour le contrôler). Ces hyperviseurs sont proches du matériel, et fonctionnent en espace noyau (kernel space). Ils sont généralement bien plus performants que les hyperviseurs de type II. Les cloud providers utilisent le plus souvent ce type d'hyperviseur pour répondre aux besoins en machines virtuelles de leurs clients.

2021-01-20-Hyperviseurs.svg
La virtualisation avec Hyperviseur Type II et Type I : on a une isolation très forte des applications au prix de plus de resources consommées pour executer un système d'exploitation invité.

Dans un container, le runtime (Docker ou autre), permet l'isolation d'un nombre limité d'applications avec leurs dépendances. Dans un container, il n'y a pas de système d'exploitation complet. On va même souvent essayer de minimiser la taille d'un container, et réduire le plus possible la quantité de composants logiciels qu'il contient. Il est même tout à fait possible de créer des containers fonctionnels qui ne contiennent qu'un fichier : le binaire à exécuter. En utilisant des languages de programmation comme Golang ou rust, c'est relativement facile à faire.

Contrairement aux machines virtuelles, les containers utilisent le système d'exploitation hôte. L'isolation est mise en place grâce à des mécanismes tels que les namespaces et les cgroups. Grâce à ces mécanismes, on peut isoler les processus du container (ils ne peuvent pas voir les processus en dehors de ce même container), et on peut facilement définir des limites de resources CPU, mémoire, IO, etc.

2021-01-20-Containers.svg
Un container est isolé du reste du système d'exploitation sans pertes de performances.

L'intérêt des containers par rapport aux machines virtuelles, c'est qu'il n'y a pas de dégradation des performances : on utilise les resources de la machine hôte aussi efficacement que si on exécutait les même binaires hors containers. Le stockage des images ne demandent souvent que quelques dizaines de méga-octets. L'isolation via des containers est donc peu demandeuse en resources supplémentaire.

Les machines virtuelles proposent une meilleure isolation que les containers. Elles permettent aussi d'exécuter n'importe quel système d'exploitation****invité sur n'importe quel autre système d'exploitation hôte.

Les machines virtuelles et les containers sont donc deux outils différents qui ne répondent pas aux même problématiques.

Sous quelle forme se présente une image de container ?

Une image de container (au format OCI) se présente principalement sous la forme de layers qui sont assemblés les uns sur les autres pour former l'image finale. Cet ensemble de layers est accompagné de méta-données et d'un manifest qui permet de définir dans quel ordre sont assemblés ces layers.

2020-01-20-docker-pull-nginx_1.19.png
Ici, la récupération de l'image de nginx met en évidence 5 layers.

Une image de container est conçue soit pour Linux, soit pour Windows. Les images Windows sont beaucoup plus volumineuses que les images Linux et sont une invention beaucoup plus récente.

Le container registry

Le container registry permet de centraliser les containers et de les rendre disponibles. Historiquement un des registry les plus utilisés est probablement le Docker Hub. Le Docker Hub est un registry public. Il en existe d'autres comme quay.io. Ces registries contiennent des images de containers officielles, et d'autres images d'utilisateurs du monde entier.

En entreprise, on utilisera plutôt des container registries privés. Il en existe qui sont gérés par les grands cloud providers, comme Amazon ECR, Google GCR, ou Azure Container Registry. On peut aussi déployer son propre registry, avec des solutions comme Portus, Harbor, et bien d'autres encore.

Attention : pour des raisons de sécurité, quand on souhaite déployer une application sous forme de container, il vaut mieux utiliser l'image qui est construite par le mainteneur de cette application. On n'est pas à l'abri de containers publiés sur une registry publique qui contiendrait du code malveillant. Utiliser une image officielle réduit ce risque (ça ne dispense pas d'auditer le contenu de ces images).

Comment l'utilisation des containers simplifie le déploiement d'applications ?

A l'époque des dinosaures 🦕, quand on voulait déployer une application, c'était sous la forme  d'un binaire. Le souci, c'est que celui-ci est susceptible d'utiliser des composants systèmes qui ne sont pas les mêmes que sur la machine où il a été construit. Cela pouvait conduire à des bugs inexplicables qui sont difficiles à corriger. C'est en général à ce moment là qu'un développeur dira : « Je ne comprends pas, pourtant ça fonctionne en local ! ».

Comme un container contient une application avec toutes ses dépendances, on ne rencontrera plus ce souci d'incompatibilité : on est sûr d'avoir un fonctionnement homogène partout où l'image est déployée.

Les services externes d'une application peuvent aussi être déployés sous forme de containers, par exemple les services de base de données. Dans ce cas, on peut définir très précisément quelle version de ces services utiliser.

Comment l'utilisation des containers simplifie le développement d'applications ?

Pour faciliter les tâches de développement, il est possible d'exploiter des propriétés des containers. Si on développe un service web et que le développeur a besoin d'un serveur de base de données MariaDB dans une version bien précise, ce n'est pas un souci : on peut déployer la version qu'on veut, localement. Ce principe est valable pour n'importe quel autre service : Redis, memcached, Elasticsearch, etc.

2020-01-20-docker-ps-mariadb_10.5.png
Ici j'ai lancé un container à partir de l'image officielle de MariaDB 10.5.

L'environnement de développement ainsi créé peut être déployé quelque soit l'OS sous lequel on travaille (ça marche aussi sous Windows et macOS).

Entre développeurs, on peut partager un fichier docker-compose.yaml qui va définir l'ensemble des services dont dépendent notre application.

Conclusion

Les containers apportent des solutions à un certain nombre de problèmes techniques. Ils permettent notamment de fluidifier le développement et le déploiement d'applications, tout en ne demandent que peu de resources.

Les containers ne se substituent pas aux machines virtuelles. Ces deux technologies sont complémentaires.

PHILIPPE CHEPY

Administrateur Système et Développeur