Pourquoi utiliser Docker en tant que dev ?

Read the article in English

Aujourd’hui, je réalise qu’il y a un réel engouement autour de la conteneurisation, et plus particulièrement de Docker. On ne cesse de me rabacher qu’en tant que dev, cela pourrait me faciliter de nombreuses tâches au quotidien. Mais comment ?

Tout d’abord, quelles sont les différences entre une VM et un conteneur ?

Différences entre VMs et conteneurs

Aujourd’hui, je travaille sur Docker. C’est l’outil qui a démocratisé la conteneurisation et qui est le plus répandu. De plus, de nombreux outils open source se basent dessus, tels que Molecule (qui permet de tester du code Ansible), ou Kubernetes (un orchestrateur de conteneurs).

Pour débuter, il y a deux objets de base à connaître : l’image et le conteneur. Une image est une « photo » de l’état souhaité de notre serveur en production : code et dépendances. C’est à partir de cette image que l’on génère des conteneurs, des « boîtes » où tourne notre code, que l’on utilise puis que l’on détruit.

Si on peut tenter une analogie avec la programmation orientée objet : une image est l’équivalent d’une classe et un conteneur est l’équivalent d’une instance de cette classe.

De plus, la philosophie des conteneurs est assez simple :

  • un processus par conteneur
  • un conteneur est immutable
  • un conteneur est jetable

Un environnement de dev iso-prod

« Un bug ? En tous cas, ça marche chez moi ! »

Que l’on soit Dev ou Ops, je pense que tout le monde a déjà entendu le fameux adage “ça marche sur mon poste”. Quand ce genre de problème survient, il se situe souvent dans les différences entre les configurations (soucis de versions, de droits) qui peuvent être difficiles à déboguer.

Un premier pas dans l’uniformisation des environnements a été entrepris avec l’introduction des machines virtuelles. Malheureusement, elles nécessitent les mêmes opérations que les machines de développement (mise à jour, configuration …).

Si mes applications sont stateless, configurables par variables d’environnement et si je respecte les standards de 12factor, alors mes conteneurs seront iso-fonctionnels avec les mêmes variables d’environnement. Cela implique que si les tests sont validés pour un conteneur alors je serai assuré que tous les conteneurs issus de la même image auront le même comportement. Car oui, utiliser un conteneur ne nous exempt pas de poser des tests !

Ainsi, l’image produite testée est utilisée en production, et on est sûrs qu’elle aura le comportement attendu. De même, si un bug se produit en production, il me suffit d’instancier un conteneur à partir de cette image avec la configuration de production pour être sûr de pouvoir le reproduire.

L'image d'un conteneur est utilisée de l'environnement de dev jusqu'à la prod

A noter que même si notre production ne fait pas tourner de conteneurs, on peut tout à fait en utiliser pour faciliter le développement de l’application.

Cependant, il faut garder en mémoire que l’introduction de Docker nécessitera un apprentissage supplémentaire. Faut-il alors favoriser un développement avec une architecture simple ou se rapprocher au plus tôt de la CI/prod et viser la reproductibilité ? À vous de décider !

Une simplification de certaines de mes tâches au quotidien

« Cela rend l’onboarding tellement plus rapide ! »

Je démarre un nouveau projet au sein d’une équipe qui utilise Docker ? Hop, j’installe Docker, je démarre le container avec la dernière version du code en cours de développement, et c’est parti ! Je suis sûr d’avoir les mêmes versions des outils que mes collègues, quel que soit l’OS sur mon poste de travail !

De plus, les montées de version sont facilitées pour toute l’équipe, et on est sûrs que tout le monde est à jour.

« Je ne veux pas polluer mon poste de dev avec tous les outils que je télécharge pour mes projets »

En tant que développeur, j’ai eu l’occasion de travailler sur plusieurs projets, et donc d’accumuler divers outils. Je me suis rapidement retrouvé confronté à un problème : j’ai plusieurs versions des mêmes outils installées sur ma machine. J’ai par exemple deux versions de PostgreSQL d’installées. Si je change de projet, je dois en désactiver une et activer l’autre. Cela me fait perdre du temps et je ne suis jamais sûr d’avoir tout bien désinstallé si je dois en supprimer une.

Disposer d’une base de données conteneurisée règle mon soucis : c’est simple à installer et à utiliser, et je suis sûr de tout supprimer à la destruction de mon conteneur !

Emprunter les outils du voisin

Prenons un exemple, je suis sur Mac et j’aurais bien aimé utiliser un outil sur Linux bien pratique : ipcalc. Avant, je me serais juste résigné et j’aurais cherché un outil similaire, mais avec un conteneur, je peux disposer de cet outil simplement !

Output de la commande ipcalc

« Je ne veux pas réinventer la roue »

L’un des avantages que j’ai découvert avec les conteneurs est celui de disposer de solutions “sur étagère”. En effet, il n’est pas pertinent de recoder une nouvelle solution à un problème déjà connu.

Il existe plusieurs endroits (on parle de registry), où trouver des images à partir desquelles instancier des conteneurs. Utilisant Docker, je suis allé sur https://hub.docker.com/ pour découvrir toutes les images disponibles et comment les utiliser. La plupart des images étant open-sources, on peut aussi contribuer à leur amélioration.

Image disponible sur le Docker Hub

Des indicateurs permettent de faire un rapide tri pour choisir : le nombre d’étoiles (données par les utilisateurs), le nombre de téléchargements de l’image, les dates de mises à jour et du dernier téléchargement.

Attention tout de même : il reste important de vérifier le contenu des images à utiliser si l’on ne souhaite pas lancer des processus malveillants (backdoored docker images).

Mais comment faire quand on n’a pas envie de publier ses images publiquement sur Docker ? Pour ça, on peut créer soi-même sa registry à partir d’une image docker (exemple : https://docs.docker.com/registry/) et déployer ses images dessus.

« Je peux réaliser mes POCs en toute sérénité »

Je peux travailler sur mes projets sans avoir peur de télécharger des packages inutiles lorsque j’ai un fichier à compiler, ou de télécharger un outil qui rentre en conflit avec des outils déjà existants sur ma machine. Il me suffit d’utiliser un conteneur et de le détruire à la fin pour laisser ma machine impeccable.

Je suis aussi plus à l’aise avec l’idée de faire des POCs, ou de tester de nouveaux outils, dans la mesure où je peux les installer dans un conteneur et supprimer ce dernier dès que je n’en ai plus besoin. C’est rapide – démarrer ou supprimer un conteneur ne prend que quelques secondes – et il me permet de simuler l’environnement exact sur lequel je souhaite travailler. Je peux aussi simplement simuler des appels à une base ou à une API. Si cela ne marche pas, il me suffit de quelques secondes pour détruire mon conteneur et en remonter un identique tout neuf !

Cela me réduit considérablement la boucle de feedback

« Mon appli est tellement compliquée à tester ! »

Sur la plupart de mes projets, j’ai une application avec sa base de données et une API qu’elle consomme. J’aimerais pouvoir tester toutes ces interactions : cela reste faisable sur mon poste, mais sur une intégration continue, cela devient compliqué.

On l’a vu, Docker me permet de rapidement monter ma base de données. De la même manière, si j’ai la main sur l’API, je peux créer son image pour la lancer dans un conteneur. Je dispose ainsi en quelques secondes d’une API de test, utilisable en intégration continue. Si je n’ai pas la main sur cette dépendance, je peux toujours créer un mock de cette API et l’utiliser de la même manière.

Docker me permet rapidement et simplement de recréer la topologie de mon projet.

Utilisation de conteneurs en tests

« Mon appli est tellement longue à tester ! »

Jusqu’à présent, lorsque je voulais tester mon code dans un environnement similaire à celui  de prod, je demandais au client de me fournir une VM. Cela pouvait prendre plusieurs semaines. Quelle perte de temps ! Et si je m’étais trompé et que j’avais besoin de détruire et de relancer une nouvelle VM, rebelote – et cela occasionne des frais supplémentaires.

Un conteneur me permet de faire tout cela sans avoir à passer par un intermédiaire, et de valider le fonctionnement de mon application et de ses dépendances.  Il faut garder à l’esprit qu’une VM est plus longue à monter et à détruire qu’un conteneur car elle réserve une partie des ressources de la machine hôte à son lancement, alors qu’un conteneur ne consomme que ce dont il a besoin.

Conclusion

Les avantages

Dans l’ensemble, en tant que développeur, l’utilisation de conteneurs peut me faciliter la vie.

  • Cela facilite le partage d’un même environnement entre devs.
  • Les dépendances seront les mêmes peu importe l’environnement. (Je suis sûr d’avoir la même version des outils que mes collègues) ?
  • Docker est cross-plateforme : les différences d’OS entre dev ne sont plus un soucis
  • Je travaille sur un environnement cloisonné.
  • Je dispose de solutions sur étagère grâce aux images open source à disposition.
  • Je peux faire des POCs rapides grâce aux images Docker sans polluer ma machine.
  • C’est plus rapide à démarrer/arrêter qu’une VM.
  • Cela accélère considérablement la boucle de feedback et la livraison en production.
  • Je suis contraint à de bonnes pratiques de dev : 12factor

À prendre en considération

Attention cependant à ne pas se lancer tête baissée dans du Docker !

  • On ne peut pas mettre n’importe quelle application dans un conteneur : il faut que celle-ci respecte les règles du 12factor app.
  • Docker propose beaucoup de fonctionnalités qu’il faut expérimenter avant de créer des topologies complexes.
  • Docker peut être moins pertinent sur des petits projets.
  • Docker introduit une complexité supplémentaire : le soucis peut venir de ma configuration, de ma topologie Docker ou de mon application.
  • Les conteneurs se basent sur le noyau de l’OS de ma machine :
    • Si j’utilise des fonctions particulières du noyau, la compatibilité sur une autre machine n’est pas assurée (ex : Docker Windows et Docker Linux ne sont pas compatibles)
    • Un processus conteneurisé peut arriver à exploiter une faille du noyau et impacter les autres processus de la machine hôte.

Enfin, il faut garder à l’esprit que Docker n’est qu’un outil parmi d’autres. On peut citer RKT (CoreOS), ou encore Windows Containers (Microsoft) par exemple. À vous de faire votre choix !

Sources

À toi de jouer !

7 commentaires sur “Pourquoi utiliser Docker en tant que dev ?”

  • Bonjour, Très bonne article de point de vue de Dévelopeur que je partagerai volontier ! Petit point, quand vous dites "On ne peut pas mettre n’importe quelle application dans un conteneur : il faut que celle-ci ait été conçue pour", je ne suis pas tout a fait d'accord, j'aurais plutôt dit : "Certaine applications peuvent difficilement tourner dans des conteneurs, (exemple: vielle appli Legacy windows). Votre tournure de phrase sous entant que l'application doit être "fait pour docker", alors qu'on peut facilement avec quelque modifications, migrer son application existante dans des containeurs. De très nombreuse chose peuvent être conteunerisés, VoIP, DNS, DHCP, PHP, Go, Java et j'en passe :) Merci en tout cas pour l'article.
  • Un autre risque des conteneurs : mon appli tourne dans mon container donc je me fiche de la rendre portable sur une distrib. Vous z'avez qu'à prendre mon container ! Bilan : des applications qui ne fonctionnent et qui ne sont validé que sur une environnement et un seul et tout le monde tourne sur le même. Un brin dangereux pour la sécurité (et la souplesse)...
  • Super article, My 2cents, comme on aime le dire, c'est également regarder du coté de LXC avec notamment vagrant. Un peu moins pratique/dev friendly, mais qui respectera un peu plus des environnements de prod qui ne sont pas sur du Docker. Avec Vagrant et LXC il est possible de rectréer des environnements de dev' sensiblement identique à la prod en profitant du fait que c'est "jetable". J'ai pas de ressources à fournir mais nous utilisons ça et ça marche plutôt bien ! Super article.
  • Bonjour, merci pour cet article, très bien réalisé. J'aurais une petite question: Quand vous envoyez votre image Docker à votre client, afin qu'il fasse donc tourner votre application dans un container en production dans les mêmes conditions que vous, vous faîtes comment pour les mises à jour de sécurité (des librairies partagées nécessaires à votre appli par exemple)? Si il y a une faille de sécurité et un patch système disponible, vous devez donc fournir à votre client une image avec les dernières mises à jour?
  • Bonjour, En effet, une image devant contenir toutes les dépendances de l'application, celles-ci ne seront pas partagées avec d'autres applications et il sera nécessaire de reconstruire une image avec les patchs de sécurité.
  • Le fameux faut pas réinventer la roue qui est pas franchement une bonne chose en soi car c'est en re réfléchissant qu'on développe des outils plus performant mais bon aujourd'hui le dev c'est surtout être jetable le plus facilement possible et reprendre quelqu'un sans devoir le reformer (puisque moins long et complexe). Pour le reste je suis plutôt d'accord sur l'utilité de docker. Après perso je l'utilise plus dans le seul bute d'isoler mon système du site développer pour mettre une couche de sécurité supplémentaire. Le reste ça reste à l'avis de l'utilisateur
  • Merci beaucoup pour les explications
    1. Laisser un commentaire

      Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *


      Ce formulaire est protégé par Google Recaptcha