Une abstraction qui ouvre de nouvelles possibilités pour la manipulation logicielle.
Permet de standardiser et de contrôler la livraison et le déploiement.
On compare souvent les conteneurs aux machines virtuelles. Mais ce sont de grosses simplifications parce qu’on en a un usage similaire : isoler des programmes dans des “contextes”. Une chose essentielle à retenir sur la différence technique : les conteneurs utilisent les mécanismes internes du _kernel de l’OS Linux_ tandis que les VM tentent de communiquer avec l’OS (quel qu’il soit) pour directement avoir accès au matériel de l’ordinateur.
VM : une abstraction complète pour simuler des machines
conteneur : un découpage dans Linux pour séparer des ressources (accès à des dossiers spécifiques sur le disque, accès réseau).
Les deux technologies peuvent utiliser un système de quotas pour l’accès aux ressources matérielles (accès en lecture/écriture sur le disque, sollicitation de la carte réseau, du processeur)
Si l’on cherche la définition d’un conteneur :
C’est un groupe de processus associé à un ensemble de permissions.
L’imaginer comme une “boîte” est donc une allégorie un peu trompeuse, car ce n’est pas de la virtualisation (= isolation au niveau matériel).
Les conteneurs mettent en œuvre un vieux concept d’isolation des processus permis par la philosophie Unix du “tout est fichier”.
chroot
, jail
, les 6 namespaces
et les cgroups
chroot
chroot
[change root : changer de racine], présent dans les systèmes UNIX depuis longtemps (1979 !) :
“Comme tout est fichier, changer la racine d’un processus, c’est comme le faire changer de système”.
jail
jail
est introduit par FreeBSD en 2002 pour compléter chroot
et qui permet pour la première fois une isolation réelle (et sécurisée) des processus.
chroot
ne s’occupait que de l’isolation d’un process par rapport au système de fichiers :
En 2005, Sun introduit les conteneurs Solaris décrits comme un « chroot sous stéroïdes » : comme les jails de FreeBSD
Les namespaces, un concept informatique pour parler simplement de…
jail
était une façon de compléter chroot
, pour FreeBSD.
Pour Linux, ce concept est repris via la mise en place de namespaces Linux
Les conteneurs ne sont finalement que plein de fonctionnalités Linux saucissonnées ensemble de façon cohérente.
Les namespaces correspondent à autant de types de compartiments nécessaires dans l’architecture Linux pour isoler des processus.
Pour la culture, 6 types de namespaces :
Après, il reste à s’occuper de limiter la capacité d’un conteneur à agir sur les ressources matérielles :
En 2005, Google commence le développement des cgroups : une façon de tagger les demandes de processeur et les appels systèmes pour les grouper et les isoler.
:(){ : | :& }; :
Ceci est une fork bomb. Dans un conteneur non privilégié, on bloque tout Docker, voire tout le système sous-jacent, en l’empêchant de créer de nouveaux processus.
Pour éviter cela il faudrait limiter la création de processus via une option kernel.
Ex: docker run -it --ulimit nproc=3 --name fork-bomb bash
L’isolation des conteneurs n’est donc ni magique, ni automatique, ni absolue ! Correctement paramétrée, elle est tout de même assez robuste, mature et testée.
On revient à notre définition d’un conteneur :
1 container = 1 groupe de process Linux
- des namespaces (séparation entre ces groups)
- des cgroups (quota en ressources matérielles)
En 2008 démarre le projet LXC qui chercher à rassembler :
Originellement, Docker était basé sur LXC. Il a depuis développé son propre assemblage de ces 3 mécanismes.
En 2013, Docker commence à proposer une meilleure finition et une interface simple qui facilite l’utilisation des conteneurs LXC.
Puis il propose aussi son cloud, le Docker Hub pour faciliter la gestion d’images toutes faites de conteneurs.
Au fur et à mesure, Docker abandonne le code de LXC (mais continue d’utiliser le chroot, les cgroups et namespaces).
Le code de base de Docker (notamment runC) est open source : l'Open Container Initiative vise à standardiser et rendre robuste l’utilisation de containers.
Docker permet de faire des “quasi-machines” avec des performances proches du natif.
VM et conteneurs proposent une flexibilité de manipulation des ressources de calcul mais les machines virtuelles sont trop lourdes pour être multipliées librement :
Les VM se rapprochent plus du concept de “boite noire”: l’isolation se fait au niveau du matériel et non au niveau du noyau de l’OS.
même si une faille dans l’hyperviseur reste possible car l’isolation n’est pas qu’uniquement matérielle
Les VM sont-elles “plus lentes” ? Pas forcément.
La comparaison VM / conteneurs est un thème extrêmement vaste et complexe.
Docker est pensé dès le départ pour faire des conteneurs applicatifs :
isoler les modules applicatifs.
gérer les dépendances en les embarquant dans le conteneur.
se baser sur l'immutabilité : la configuration d’un conteneur n’est pas faite pour être modifiée après sa création.
avoir un cycle de vie court -> logique DevOps du “bétail vs. animal de compagnie”
Docker modifie beaucoup la “logistique” applicative.
uniformisation face aux divers langages de programmation, configurations et briques logicielles
installation sans accroc et automatisation beaucoup plus facile
permet de simplifier l'intégration continue, la livraison continue et le déploiement continu
rapproche le monde du développement des opérations (tout le monde utilise la même technologie)
Permet l’adoption plus large de la logique DevOps (notamment le concept d’infrastructure as code)
Docker est la technologie ultra-dominante sur le marché de la conteneurisation
LXC existe toujours et est très agréable à utiliser, notamment avec LXD (développé par Canonical, l’entreprise derrière Ubuntu).
Apache Mesos : un logiciel de gestion de cluster qui permet de se passer de Docker, mais propose quand même un support pour les conteneurs OCI (Docker) depuis 2016.
Podman : une alternative à Docker qui utilise la même syntaxe que Docker pour faire tourner des conteneurs OCI (Docker) qui propose un mode rootless et daemonless intéressant.
systemd-nspawn : technologie de conteneurs isolés proposée par systemd