Lors de mon précédent article sur Docker, j’ai essayé de vous montrer l’intérêt que peut avoir cette technologie dans le développement de vos prototypes et projets frugaux. Souhaitant continuer sur cette lancée, j’ai décidé de rentrer un peu plus dans le vif du sujet, et vous propose de réaliser cette fois-ci un « squelette » d’image Docker.

 

Un squelette ? Mais quelle idée morbide !

Rien de mortuaire ici, je parle simplement de squelette par opposition à une image finie. En effet, une image au sens Docker du terme consiste en un projet fini, prêt à être employé et décliné en container.

Notre squelette ne sera donc pas une image finie, mais un modèle d’image, que vous pourrez adapter à tous vos besoins. Ici, le but de ce squelette sera de lancer automatiquement un script au démarrage du container et, petit bonus, pouvoir monitorer son exécution.

Grâce à votre nouvel ami le squelette, chaque fois que vous aurez besoin de dockeriser un script, vous n’aurez qu’à faire un simple copier-coller du projet, y insérer votre script, et lancer votre container.

Cependant, je vous montrerai dans ce tutoriel uniquement comment dockeriser un script Python ; selon le langage utilisé, il faudra peut-être procéder à quelques adaptations, si vous ne voulez pas tomber sur un os. Mais n’anticipons pas trop vite, et commençons toute suite la réalisation.

Illustration de squelette Docker par le génial Clément De Ruyter (http://clement-dr.tumblr.com/)
Illustration par le génial Clément De Ruyter (http://clement-dr.tumblr.com)

 

Des membres aux membres

Tout projet Docker s’articulant autour d’un Dockerfile, nous commencerons bien sûr par là. Je vous propose donc de créer le dossier dans lequel nous allons travailler, que nous nommerons par exemple « python_script_docker ». Oui, je ne suis pas fracassé le crâne pour trouver un nom, mais au moins on sait tout de suite ce que cela contient. Créez maintenant votre fichier nommé Dockerfile à l’intérieur du dossier.

Nous allons maintenant, couche par couche décrire ce dont nous avons besoin. Commençons donc par l’image sur laquelle nous nous baserons :

Bien, ce fut intensif. Je vous propose donc une petite pause pour vous détailler un peu la suite. Je vous ai parlé de lancer et monitorer un script. Toujours dans une démarche frugale, nous éviterons donc de nous fêler une côte en redéveloppant un outil de monitoring, quand nous pouvons simplement en trouver un tout fait.

Nous utiliserons donc un outil léger et facile à prendre en main nommé Monit. Doté d’une interface simpliste mais tout de même efficace, il vous permet de suivre, stopper, et relancer l’exécution de scripts depuis une page web.

Nous allons donc rajouter dans notre Dockerfile la ligne suivante, qui inclut les outils dont nous aurons besoin pour installer Monit :

Pour l’instant, rien d’inconnu donc ; je vous propose cependant d’utiliser une nouvelle commande Docker :

Comme vous l’aurez peut-être deviné, ENV vous permet de déclarer une constante dont nous nous servirons dans le Dockerfile pour représenter le numéro de version de Monit. Nous aurions pu faire sans, mais cela nous permettra de changer facilement de version lorsque nous le souhaiterons. On va donc rajouter deux commandes pour pouvoir télécharger Monit et l’installer :

Grâce à ces deux lignes, Monit sera installé dans le dossier « /usr/bin/monit » de notre future image. Intéressons-nous donc maintenant à la configuration de Monit.

 

Ossature d’une configuration Monit

Je vous ai brièvement expliqué le fonctionnement de Monit. On va donc rentrer un peu plus dans le détail, en analysant rapidement l’interface graphique du logiciel :

Interface graphique principale de Monit
Interface graphique principale de Monit

Sur cet exemple d’interface de Monit, vous pouvez voir la liste des processus qui sont monitorés par le programme, ainsi que leur état, leur durée d’exécution, etc. En cliquant sur un des processus, vous pourrez obtenir plus de détails dessus, et l’arrêter ou le relancer. Comme je vous l’avais promis, Monit est un outil très simple d’utilisation, et largement suffisant pour la plupart des besoins de monitoring.

Comme tout bon logiciel, Monit utilise un fichier de configuration, appelé « monitrc ». Créez donc ce fichier dans la racine du dossier du projet, et éditez-le avec les lignes ci-dessous.

Ceci est relativement simple, mais j’ai néanmoins détaillé ces lignes une par une. N’oubliez pas de retirer les commentaires lors de la copie, sinon cela risque de ne pas fonctionner !

On a maintenant une configuration basique au possible, mais qui ne se trouve pour le moment que dans le dossier projet : il ne reste donc plus qu’à la copier dans l’image.
Ajoutez donc les lignes suivantes à votre Dockerfile :

 

Le script, c’est chic !

Maintenant que Monit est configuré, nous allons pouvoir lui fournir un script à monitorer. Comme je l’écrivais en début d’article, je parlerai ici d’un script Python ; n’hésitez cependant pas à utiliser ce que vous souhaitez, en procédant aux changements qui s’imposent.

Nous prendrons ici un petit script permettant d’envoyer en boucle un message MQTT :

Si tout fonctionne correctement, au lancement de notre container, ce script sera lancé et monitoré par Monit, et enverra toutes les 10 minutes un message MQTT sur mqtt.frugalprototype.com. Ceci peut servir à vérifier qu’il a bien été lancé.

Créez donc un repertoire « scripts » dans votre dossier de projet, et à l’intérieur, le fichier « main.py », dans lequel vous insérez le script sus-décrit.

Retournez maintenant sur votre Dockerfile, et ajoutez-y les lignes suivantes :

Ceci créera donc le dossier /scripts dans le container, et y copiera le contenu du dossier scripts de votre projet.

J’ai ici fait exprès de prendre un script utilisant un module python externe : paho-mqtt. Il va donc falloir que notre container installe ce module pour pouvoir l’utiliser ; c’est un très bon moyen pour découvrir Pip.
Pip est un utilitaire Python très pratique qui permet d’installer facilement de nouveau modules. Il s’utilise comme suit :

Une autre manière d’utiliser Pip, que nous allons utiliser dans notre cas, est de se servir de fichiers pour lister l’ensemble des modules à installer.

Dans votre dossiers scripts, créez donc le fichier « requirements.txt », et dedans, écrivez simplement « paho-mqtt », et sauvegardez.

Puis, dans votre Dockerfile :

Au lancement du container Docker, Pip s’occupera donc d’installer tous les modules Pythons que vous aurez listé dans ce fichier.

 

Wrapper sur la ville

Comme je vous sens déjà sur les rotules, je vais essayer de rester concis dans ce paragraphe, qui aborde un sujet un peu complexe.

Pour monitorer un processus, Monit se sert de fichiers nommés « PIDfiles ». Ce sont des fichiers dans lesquels sont inscrits les « numéros » de chaque processus en cours sur la machine.
Le problème avec les scripts est qu’il ne fonctionnent pas avec ces PIDfiles, et ne peuvent donc pas être monitorés par défaut.

On va donc ici se servir d’un « wrapper », ou « emballage », qui s’occupera pour nous de créer ce PIDfile. On transformera ainsi notre simple script en quelque chose qui s’apparente à un « daemon » ou service.

À la racine du projet, créez le fichier « mqtt_publisher », notre futur wrapper, et collez ces lignes à l’intérieur :

Dans le Dockerfile, entrez les deux lignes ci-dessous, pour placer le wrapper dans le dossier des services (init.d) et le rendre exécutable.

Grâce à ce wrapper, vous pourrez maintenant lancer votre script grâce à la commande « mqtt_publisher start ». C’est d’ailleurs ce que Monit fera lui-même.
Si vous vous souvenez, lors de la création du fichier monitrc précédemment, nous avions ajouté la ligne suivante :

Cette ligne indique à Monit le répertoire dans lequel il trouvera quels scripts il doit monitorer, et leurs configurations.
Nous allons donc créer ce dossier et son contenu dans notre dossier de projet, et l’envoyer dans l’image Docker grâce au Dockerfile.

Créez donc le dossier « conf.d » à la racine de votre projet, et à l’intérieur, un fichier nommé « mqtt_publisher », dans lequel vous entrez ces lignes :

Vous vous en doutez, c’est ici qu’est faite la liaison avec le wrapper que nous avons écrit plus tôt : Monit se servira de ce fichier pour trouver le PIDfile de notre script, ainsi que les commandes pour le lancer et le stopper.

Encore une fois la même manipulation, on ajoute donc une ligne au Dockerfile pour copier le contenu de notre dossier conf.d au dossier /etc/monit/conf.d :

Et voilà ! Au lancement de Monit, notre script Python devrait être exécuté et monitoré.

 

Le Docker sur la main

Pour finaliser notre projet, il ne nous reste plus que quelques lignes à ajouter à notre Dockerfile, mais pas des moindres.
Tout d’abord, nous avons utilisé plusieurs outils dans les différentes commandes du fichier, et pour ne pas avoir à revenir là-dessus à chaque fois, j’ai préféré attendre la fin de ce tutoriel pour écrire, en une seule fois, la ligne permettant de les installer ; la voici donc :

Ces outils étant utilisés tout au long du Dockerfile, il faut bien penser à les installer au début du fichier, soit à la troisième ligne par exemple ; sinon, vous risquez d’obtenir quelques erreurs !

Enfin, il ne reste plus qu’à rendre disponible le port utilisé par Monit (2812, comme défini dans le monitrc), et bien entendu, lancer Monit au démarrage du container :

Ceci est naturellement à écrire à la toute fin du Dockerfile.
Il devrait donc ressembler maintenant à ceci :

Il ne nous reste plus qu’à compiler l’image !
À la racine du projet, lancez donc la commande build, puis la commande run si le build s’est correctement passé :

Pour rappel, le paramètre « -p 2812:2812 » de la commande Docker run permet de mapper un port du container sur le port de la machine hôte.
Pour accéder à l’interface de Monit, il suffira donc, depuis votre navigateur, de vous rendre à l’adresse « localhost:2812 ».
Vous pourrez ainsi voir le statut de l’exécution de votre script Python.

Attention, il est possible que Monit vous affiche initialement une erreur sur l’exécution du script ; cela arrive généralement avec cette configuration. Mais normalement, au bout de 30 secondes, Monit réactualise l’interface et le script apparaît correctement en « running ».

Revenons à nos squelettes de moutons

Nous avons donc réalisé ici une image fonctionnelle, mais générique. Il vous suffit en effet de remplacer le script contenu dans le répertoire « scripts », ainsi que le fichier « requirements.txt » pour lancer le script de votre choix. Bien entendu, et selon les cas, il vous faudra en plus fournir une certaine quantité d’huile de coude pour adapter votre image selon le besoin ; mais néanmoins, vous avez ici quelque chose de relativement prêt à l’emploi, et surtout, vous avez étendu votre connaissance de ce formidable outil qu’est Docker !

Pour ceux qui souhaiteraient gagner un peu de temps, vous pouvez retrouver ce projet sur mon GitHub : https://github.com/RayBor/docker_image_python_monit
N’hésitez pas à nous faire savoir ce que vous avez pensé de l’article, si vous l’avez trouvé utile, et si vous avez réussi à utiliser dans vos projets ce que vous avez appris.

Si des erreurs se sont glissées dans l’article, n’hésitez pas non plus à nous en faire part.

À bientôt sur Frugal Prototype !


Raymond Borenstein
Raymond Borenstein

Spécialisé dans les applications et objets connectés, j'aime faire communiquer ensemble tout ce que je peux.

All author posts
Related Posts

Privacy Preference Center