Plus besoin de présenter Docker, depuis sa création en 2013, il a très vite été adopté et a démocratisé les conteneurs. Incontournable à ses débuts, ce n’est plus le cas; les standards de l’ Open Container Initiative (entre autres) ont permis l’émergence d’alternatives stables offrant d’autres fonctionnalités. Ces alternatives sont tellement solides que Kubernetes a même décidé de déprécier Docker en tant que runtime CRI (Container Runtime Interface) à partir de la version 1.20.
Cet article est le premier d’une série traitant de Docker et de ses alternatives, ainsi que des technologies de conteneurs en général.
Avant d’aller plus loin, commençons par les fondamentaux. Nous regarderons ensuite de plus près Docker et ses usages, puis l’OCI et ses standards.
Le concept d’un conteneur applicatif est de packager une application et toutes ses dépendances de façon à l’isoler de l’environnement extérieur (l’OS, les autres applications…). Une méthode serait d’isoler cette application dans une machine virtuelle dédiée, mais cette solution est bien trop lourde pour une bonne partie des applications actuelles.
La méthode la plus communément utilisée, notamment par Docker, est d’utiliser les fonctionnalités du kernel Linux de la machine hôte afin d’encapsuler l’application et ses dépendances dans un conteneur pour aboutir à une solution plus légère et performante qu’une machine virtuelle classique. Le conteneur ne contient donc rien d’autre que l’application, ses dépendances et une arborescence de fichiers classiques d’OS au besoin.
Afin d’isoler un maximum le conteneur du reste du système, les conteneurs utilisent une combinaison des fonctionnalités suivantes du kernel Linux.
Les namespaces de différents types, dont :
Les cgroups permettent de restreindre les ressources CPU et RAM. Si le conteneur essaie d’utiliser plus de CPU qu’il n’en a le droit, il sera simplement limité. S’il essaie d’utiliser plus de RAM, il se fera tuer (OOM Killed).
Les Linux Security Modules (LSM) qui permettent de limiter les appels systèmes. Seccomp, AppArmor et SELinux sont des exemples d’implémentation de ce framework.
La combinaison de ces fonctionnalités permet la création de conteneurs légers et isolés du reste de la machine. Les principaux bénéfices de cette approche sont :
Maintenant que le concept de conteneur applicatif est un peu plus concret, regardons de plus près Docker et ses usages.
Docker est un outil aux multiples usages, il permet entre autres de télécharger des images, de lancer des conteneurs, d’en construire et de redémarrer les conteneurs qui s’arrêteraient inopinément…
Il est également utilisé par des personnes aux rôles diverses, que ce soit le développeur pour tester rapidement une application ou construire localement des conteneurs, l’expert DevOps qui sera en charge de construire les images et de les distribuer dans un pipeline de CI/CD ou encore l’administrateur qui maintiendra le conteneur en production.
Docker est également utilisé par des orchestrateurs de conteneurs tels que Kubernetes.
Face à tous ces usages et profils d’utilisateurs, nous pouvons découper les outils de conteneurs comme ceci :
Nous consacrerons également un article sur les container runtimes : se sont les outils de plus bas niveau permettant de lancer les conteneurs. Docker n’en est pas un mais en utilise un interne.
Docker permet donc de faire à peu près tout ce que l’on souhaite avec les conteneurs. Les autres outils s’appuient sur les standards basés sur Docker pour venir enrichir le panel d’outils disponibles.
Docker et les acteurs majeurs de l’industrie du conteneur fondent l’ Open Container Initiative en juin 2015 dans le but de développer des standards. Cette structure est sous la houlette de la Linux Foundation . Docker donne son runtime de conteneur, runc , ainsi que les bases des standards actuels.
Aujourd’hui l’OCI porte deux spécifications : la spécification de runtime ( runtime-spec ) et la spécification d’image ( image-spec ).
La spécification d’image définit ce qu’est une OCI image. Elle est composée :
Ces OCI Images sont construites par ce que nous appelons un builder (cf. Docker et ses usages), comme Docker , Buildah ou Kaniko .
Une OCI Image peut ensuite être extraite en “filesystem bundle”, qui sera ensuite lancée par un outil implémentant l’OCI Runtime specification, plus communément appelé OCI runtime ou container runtime.
Une autre spécification majeure existe, il s’agit de la Container Runtime Interface de Kubernetes. Celle-ci sera abordée dans notre prochain article consacré aux implémentations de cette spécification.
Les conteneurs sont maintenant très utilisés, en particulier grâce à Docker. Celui-ci permet de faire beaucoup de choses avec les conteneurs et s’adresse à de nombreux utilisateurs différents. Tous ces usages peuvent être décorrélés et exécutés par d’autres outils grâce aux standards de l’industrie comme ceux de l’OCI, comme le pipe du shell permet de connecter cat et sed par exemple.
D’autres articles de cette série sont disponibles, si vous voulez en apprendre plus sur les container engines ou les builders nous vous laissons les consulter ! D’autres sur les container runtimes et les implémentations du CRI de Kubernetes vont arriver. En attendant le prochain épisode, n’hésitez pas à aller consulter notre article sur comment adopter une approche Kubernetes First !
Pour aller plus loin, voici quelques articles qui pourraient vous intéresser :
Merci de nous avoir contactés.
Nous reviendrons vers vous dès que possible.
Oups ! Une erreur s'est produite lors de l'envoi de votre message.
Veuillez réessayer plus tard.