PROJET AUTOBLOG


Le blog de Seboss666

Site original : Le blog de Seboss666

⇐ retour index

Le socle technique actuel du blog

lundi 22 janvier 2018 à 19:00

On m’a demandé récemment par mail des conseils pour améliorer la réactivité d’un blog WordPress, en comparant le mien qui serait bien plus rapide. Je n’ai pas encore de réponses définitives sur le sujet mais je pense utile de partager de manière globale les détails de l’hébergement actuel, histoire de pouvoir comparer proprement. Et quelques pistes pour savoir où trouver ce qui coince.

En effet, la description de l’infrastructure est éclatée entre un nombre beaucoup trop grand de billets éditos et autres pour en tirer quelque chose d’exploitable. On va donc reprendre couche par couche, histoire de savoir de quoi on parle.

Le matériel

Le serveur physique est un minisp32 de 2014 chez OVH localisé à Strasbourg. Il embarque un processeur Intel Xeon E3-1245v2, est accompagné de 32Go de RAM et deux disques de 2To dont la configuration peut varier via le système d’exploitation installé. Il dispose en outre d’une carte ethernet gigabit et l’abonnement d’OVH « garantit » un débit de 500Mbits par seconde. Bref, une bonne machine qui malgré les années qui commencent à s’accumuler nous a rarement fait défaut.

Le logiciel

Plus gros morceau, mais on va tout de même le faire dans l’ordre, du plus loin au plus près du blog.

L’os principal de la machine est Proxmox VE, un hyperviseur pour virtualisation qui repose sur un noyau Linux et donc les technologies lxc (containerisation d’os) et kvm (virtualisation complète). L’installation made in ovh configure les disques durs en raid 1 (miroir) ce qui sécurise un poil les données, même si ça ne remplace pas les sauvegardes.

Qui dit virtualisation dit machines virtuelles, et en l’occurrence on exploite des machines kvm. Celle qui héberge le blog, entre autres, est une machine sous Debian 8 Jessie (stretch en cours de validation). Je lui ai attribué 3vCPU et 6Go de RAM, et le disque est un assemblage avec LVM de deux volumes (petite extension suite à un besoin d’espace).

On parle d’hébergement web, et sans surprise on retrouve le tryptique de base qui est assuré par le serveur web Nginx (dépot dotdeb http2), le langage PHP 7.0 est fourni par dotdeb également (en mode FPM), et MariaDB 10 s’occupe de la base de données. En complément, j’ai ajouté un service Redis histoire de délester un peu la base de données suite aux problèmes de performances de disque certainement du à LVM (les images ne sont pas au même format, entre autres). Je pourrais également stocker les sessions dans Redis si j’étais motivé.

Et donc, le blog est propulsé par WordPress, avec un thème responsive (un seul thème pour couvrir tous les appareils), et quelques plugins pour ajouter quelques fonctionnalités plus ou moins visibles : postage sur les réseaux sociaux, affichage embarqué des images, barre de progression de lecture, vérification des liens cassés…

Comment j’ai amélioré les performances ?

On a déjà un socle qui a du muscle à plein de niveaux, matériels et logiciels. Mais ça ne fait pas tout. Je limite les extensions que j’utilise, et celles que j’utilise sont dans l’ensemble de qualité, pas trop lourdes (une extensions pour une tâche), certaines fonctions ont été intégrées dans le thème, qui a également été choisi pour ne pas être trop lourd. La taille de chaque page est contrôlée pour ne pas être lourde à charger même sur une connexion un peu souffrante (j’ai démarré le blog quand j’habitais encore chez ma mère, donc je fais toujours attention à ça).

J’ai fait quelques réglages sur PHP histoire de bosser comme il faut en mémoire vive (taille confortable pour l’opcache entre autres), pareil pour la base de données, qui a finalement eu le plus de boulot : pools innodb, index supplémentaires, écart sur la conformité CRUD… Et donc Redis, dans lequel WordPress stocke le contenu de plusieurs objets, articles, commentaires, pour éviter de refaire les requêtes en base de données, certaines étant particulièrement peu efficaces et peu optimisables.

Et… C’est à peu près tout, mais faut dire que c’est déjà beaucoup plus que ceux qui font un « apt install nginx php mariadb-server » et qui mettent leur site en ligne 10 minutes plus tard sans plus de configuration.

Pourquoi le site à qui il est comparé peut-il être plus lent ?

Le site en question est hébergé sur un Synology DS1515+. Il est propulsé par un Intel Atom C2538 qu’on aurait aimé avoir dans des laptops plutôt que les bousasses grand public qu’on a subi dans des netbooks pendant des années. Il est accompagné de 16Go de RAM (quand la fiche technique annonce un max supporté de 6Go, mais c’est pas grave), et la grappe de stockage fait 40To et composée de disques à 7200 tours par minute avec 256Mo de cache.

Pas du matos de merde donc, mais en dehors du stockage, on a un CPU bien moins puissant que ma grosse bertha, mais dont la principale particularité est de consommer 4 fois moins. On a rien sans rien. Mais la puissance brute n’est pas seule responsable d’un éventuel écart. Si on se réfère à ce comparatif de CPUBoss, le support d’extensions de jeu d’instructions est inexistant ou presque sur l’Atom, et ça peut avoir des conséquences importantes sur plusieurs points de fonctionnement de PHP (compilation JIT), MariaDB, et du serveur web (s’il y a du HTTPS une partie peut être gérée par le CPU via AES-NI, c’est pas mal même si c’est pas le but premier de l’intégration du jeu d’instructions). Ensuite on parle d’un NAS, et donc, la connexion qui permet d’accéder au site est certainement plus légère que celle que me fournit OVH. En particulier au niveau de l’upload, et là, y’a pas de mystère, c’est pas en France sur des connexions grand public qu’on égalera une connexion d’un datacenter, les rares qui auront droit à du vrai FTTH avec un upload qui soit pas misérable vont se compter en dessous de la dizaine de pourcents (soit au delà de 200Mbps, je sais, mais je pourrais faire un article complet sur les raisons de ce palier qui parait hallucinant).

Et un autre point qui pourrait être finalement plus important que les autres : la version et la configuration des composants. Que ce soit Nginx, PHP, MariaDB (j’ai pas encore profondément mis les mains dans Redis mais j’ai du taf pour sûr), j’ai passé un peu de temps à régler chaque composant, à analyser un peu son comportement, faire des choix par rapport à mon usage. Concernant Nginx, ça tient d’abord aux nombre de processus (workers), et au nombre de connexions absorbables par ceux-ci, plus un mode HTTP2 s’il est exploitable par les navigateurs. Pour PHP, la version 7 est vraiment un coup de fouet par rapport aux précédentes, et le mode de fonctionnement d’FPM, les modules installés, la quantité de mémoire utilisée pour certains d’entre eux a été analysée. Pour MySQL/MariaDB, idem, 10.0 apporte déjà son lot d’améliorations de performances, et l’utilisation intensive de mysqltuner m’a permis de faire pas mal de corrections sur InnoDB pour en tirer le maximum. Enfin, si je n’avais pas les outils de bases comme htop, iftop, iotop, pour analyser en temps réel le comportement de la machine, j’aurais certainement raté quelques éléments.

Car vous pourrez disposer de toute la puissance brute que vous voulez, ça pourra masquer de grosses erreurs de configuration pendant un temps, mais ça ne fera pas de miracles non plus. C’est une sacrée recette de cuisine qu’on a là, et malgré le peu d’ingrédients à y inclure, on est un peu au delà de la méthode couper/foutre.

WordPress est-il le bon outil ?

Beaucoup pensent qu’on peut tout faire avec WordPress, et que c’est pour ça qu’il est utilisé par plus d’un quart des sites web référencés par les moteurs de recherche. J’ai tendance à penser que non, sinon il y aurait encore plus de monde dessus et bien moins de technologies et de moteurs pour construire des applications web dans différents langages. J’ai pu voir du WordPress pour présenter un site vitrine, un blog en tant qu’annexe d’un autre site,  une plateforme de commerce (j’en ai un qui passe en prod fin mars d’ailleurs), un moteur d’API pour une application écrite en Javascript sur une page HTML à part — un usage curieux tant les outils pour construire des API plus légères sont légions et bien documentés. Pire, j’ai vu le backoffice d’un WordPress multisites torturé pour en faire un intranet (hébergé sur AWS d’ailleurs, on notera l’ironie de « l’intra » dans ce cas), ce qui occasionne régulièrement des problèmes de fonctionnement, certaines tâches n’étant pas taillées pour fonctionner en mode web. Un autre tente de construire une sorte de réseau social, mais il est déjà acté que finalement WordPress va devenir trop limitant, aussi bien pour les performances que les fonctionnalités.

Bref pour chacun de ces usages, il y a certainement des outils plus adaptés que WordPress. Dans le cadre de mon contact, après avoir visité le site il n’y a rien à redire dans le rôle qu’il tient, c’est le bon outil bien que d’autres auraient pu tout aussi bien convenir (SPIP, Pluxml…). Le reste peut donc venir d’un ou de plusieurs des éléments que j’ai mentionné plus haut, et je vais donc reprendre le boulot par mail ou un autre canal pour qu’on essaie de tirer la quintessence de son installation. Et vous, vous avez maintenant des billes pour chercher d’où peut venir votre problème. D’ailleurs, j’ai peut-être oublié des choses, auquel cas, juste en dessous il y a un autre outil bien utile et adapté, les commentaires 😉

 

Une très bonne/mauvaise année 2018

mercredi 17 janvier 2018 à 18:30

Je sais je suis pas en avance, en plus j’avais même pas fait de message pour Nowel. On va la faire courte, je suis pas super inspiré, après avoir tenté les deux techniques de vœux de nouvelle année pour qu’on ait pas une année trop pourrie, à titre personnel tout va bien même sans avoir tenu certaines des inévitables résolutions que l’on pose à chaque nouvelle année; on ne peut pas en dire autant de notre civilisation, plus que jamais mal en point.

On aborde donc 2018 avec un Macron en train de déconstruire le pays pour le donner aux multinationales, un Trump qui joue au kikalaplugross avec un nabot aussi débile et timbré que lui, et je ne sais quoi encore qui, mois après mois, ne donne plus super envie de vivre sur cette planète (Elon, grouille-toi de nous amener sur Mars qu’on recommence à zéro).

Et pourtant, je compte continuer de participer à ma mesure à une entraide pour les plus démunis face à notre numérisation à marche forcée de la société, à mettre en lumière les travers dans lesquels mes contemporains plongent sans en être conscient (destruction de la vie privée, aussi bien par les états et les sociétés privées), et même tenter de me « detroglodytiser » un peu plus, rencontrer physiquement plus de gens même si je reste plus à l’aise derrière un clavier. Ce dernier point étant probablement le plus compliqué pour moi, bizarrement.

Je vais alors jouer la carte suivante : aux personnes respectables (hors majorité des personnalités politiques donc), que vos projets se réalisent et embellissent votre vie; à tous les autres (dont la majorité des personnalités politiques, et les cons–ces deux groupes ne sont pas exclusifs), allez crever en enfer. Ceci dit, il m’arrive régulièrement de me traiter moi-même de débile, ne suis-je pas dès lors en train de me souhaiter une mauvaise année, ce qui semble bien parti avec une voiture en train de rendre l’âme et un point en moins sur le permis ?

PS : les brouillons avancent, au ralenti, mais ils avancent, un jour ça sortira. Je sais juste pas quand…

Modem 4G Huawei E3372 sous Linux, pas super accessible…

vendredi 12 janvier 2018 à 18:30

Sachant qu’Orange ne veut pertinemment pas corriger le pépin de la ligne téléphonique de ma mère qui continue de payer son abonnement (et Free la location de la boucle), abonnement qui fonctionne seulement la moitié du temps (remember la présentation de Grafana, c’était pour ça), la fibre étant promise pour le « premier trimestre 2018 » j’ai décidé de tenter l’aventure de la clé 4G le temps que ça arrive. Clé reçue en 24h, carte sim Free en moins d’une semaine, et même si au final la clé sera utilisée sous Windows, j’ai évidemment voulu la tester sous Linux. J’ai bien fait, c’est pas aussi simple qu’on le pense au premier abord.

Disclaimer : Tout ne sort pas de mon cul non plus, je me suis grandement basé sur l’excellent article bourré d’infos du site lecrabeinfo.net. Vu les moyens à engager pour avoir un full réseau (avec routeur WiFi à modifier pour passer à OpenWRT), je me suis arrêté à la première étape, avoir du réseau le plus simplement possible.

Comment ça une clé USB Mass Storage ?

En effet, j’ai branché la clé après avoir inséré la carte SIM, et tout ce que le noyau me dit, c’est qu’il a reconnu un USB Mass Storage, et un lecteur CD qui n’arrive pas à s’initialiser (contient notamment les éventuels logiciels de gestion sous Windows…) :

[seboss666@seboss666-ltp ~ ]$ lsusb
Bus 001 Device 002: ID 8087:8001 Intel Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 005: ID 12d1:1f01 Huawei Technologies Co., Ltd. E353/E3131 (Mass storage mode)
Bus 002 Device 004: ID 5986:024b Acer, Inc 
Bus 002 Device 003: ID 8087:07dc Intel Corp. 
Bus 002 Device 002: ID 062a:5918 MosArt Semiconductor Corp. 
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

La notice, naturellement, vous demande de vous tourner vers le logiciel de gestion windowsien pour exploiter la clé. Dans le cul donc. J’avais réactivé ModemManager dans l’espoir qu’il détecte quelque chose, mais non. J’ai trouvé ma solution grâce à une recherche Qwant, en anglais évidemment, donc je vous explique ce que j’ai fait pour la culture. Je n’ai pas suivi l’intégralité de l’article, donc libre à vous si son cas d’utilisation vous convient.

En fait, la clé peut évidemment fonctionner dans plusieurs modes, celui qui m’intéresse est le mode carte Ethernet USB, qui est pratiquement universel sous Linux, et notamment celui qu’on utilise lorsqu’on active le partage de connexion USB de son smartphone. Mais pour ça, il faut bricoler un peu.

On commence par installer le paquet usb_modeswitch sur ma Manjaro (usb-modeswitch sous Debian/Ubuntu), ensuite via sudo on crée/remplit le fichier /etc/usb_modeswitch.conf :

# Huawei E353 (3.se) and others
 TargetVendor=0x12d1
 TargetProductList="14db,14dc"
 HuaweiNewMode=1
 NoDriverLoading=1

Pour le détails des identifiants, se reporter à l’article original, mais bon ça va nous permettre de changer le mode de la clé, avec la commande suivante :

sudo usb_modeswitch -v 12d1 -p 1f01 -c /etc/usb_modeswitch.conf
Look for target devices ...
 No devices in target mode or class found
Look for default devices ...
 Found devices in default mode (1)
Access device 005 on bus 002
Get the current device configuration ...
Current configuration number is 1
Use interface number 0
 with class 8
Use endpoints 0x01 (out) and 0x81 (in)
Using standard Huawei switching message
Looking for active drivers ...
 OK, driver detached
Set up interface 0
Use endpoint 0x01 for message sending ...
Trying to send message 1 to endpoint 0x01 ...
 OK, message successfully sent
Read the response to message 1 (CSW) ...
 Response successfully read (13 bytes), status 0
Reset response endpoint 0x81
 Could not reset endpoint (probably harmless): -99
Reset message endpoint 0x01
 Could not reset endpoint (probably harmless): -99
 Device is gone, skip any further commands
-> Run lsusb to note any changes. Bye!

Quelques secondes plus tard, on devrait avoir ça :

[seboss666@seboss666-ltp ~ ]$ lsusb
Bus 001 Device 002: ID 8087:8001 Intel Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 006: ID 12d1:14dc Huawei Technologies Co., Ltd. E33372 LTE/UMTS/GSM HiLink Modem/Networkcard
Bus 002 Device 004: ID 5986:024b Acer, Inc 
Bus 002 Device 003: ID 8087:07dc Intel Corp. 
Bus 002 Device 002: ID 062a:5918 MosArt Semiconductor Corp. 
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Dans mon cas deux secondes plus tard NetworkManager m’indiquait être relié à un nouveau réseau. On y est presque !

Et maintenant, comment qu’on rentre son code PIN et qu’on teste sur nPerf ?

En effet, je n’ai pas rentré le code pin de la carte SIM, donc pas de connexion « internet » pour l’instant. Une petite inspection me permet de vite trouver mes petits :

[seboss666@seboss666-ltp ~ ]$ ip a
(...)
4: enp0s20u7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
    link/ether 0c:5b:8f:27:9a:64 brd ff:ff:ff:ff:ff:ff
    inet 192.168.3.10/24 brd 192.168.3.255 scope global dynamic noprefixroute enp0s20u7
       valid_lft 86359sec preferred_lft 86359sec
    inet6 fe80::a7b2:408a:e123:9435/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[seboss666@seboss666-ltp ~ ]$ ip route show
default via 192.168.3.1 dev enp0s20u7 proto dhcp metric 20100 
192.168.3.0/24 dev enp0s20u7 proto kernel scope link src 192.168.3.10 metric 100

J’ouvre donc un énième onglet dans Firefox, et tape l’adresse http://192.168.3.1 : Paf ça fait des Chocapic ! Je tombe sur l’interface me demandant de saisir le code PIN (et me propose de l’enregistrer pour ne plus avoir à le saisir à l’avenir, faites comme vous le sentez). Dans l’excitation du moment je n’ai pas pris le temps de faire de capture d’écran.

J’avais tout de même un souci : après la saisie, le voyant clignote encore un peu et se fixe sur un Cyan sans clignoter. Petite notice qui dit qu’on est sur un 3G+/4G. Vérification sur l’interface, en effet, il dit être relié en 4G, mais la force du signal est pas dingue. Dans les paramètres réseau, on peut décocher l’option Prise en charge des réseaux 4G.

Moins de deux secondes plus tard, ça fonctionne :

<script async src="https://platform.twitter.com/widgets.js" charset="utf-8">

Le débit est pas ouf chez moi, mais j’ai l’intention de tester évidemment chez ma maman, mais je sais déjà via les techniciens Free qui sont passé que la couverture est pas trop dégueulasse malgré la distance des antennes (dans ma chambre c’était du full 4G). C’est donc une victoire ! (d’ailleurs pour pas perdre trop de choses, j’ai écrit la majorité de cet article via la connexion 3G tant que c’était frais 😀 )

Y’a encore du chemin à faire

Imaginez quelqu’un qui est un utilisateur basique d’une distribution Linux, qui se retrouve à devoir utiliser ce genre de solutions (ma frangine s’est vu « offrir » une clé 3G par Orange pendant qu’il ne voulait pas engager les travaux pour déployer un nouveau faisceau de ligne pour la raccorder en ADSL moisi). À qui dans mon entourage hors bricoleurs je peux dire « ben avec usb_modeswitch ça va tout seul, ensuite tu bricoles sur l’interface web de la clé et roulez jeunesse » ? Non, ça ne fonctionne pas.

Il y a donc encore des progrès à accomplir sur ce terrain, je ne dis pas que c’est évident, facile à faire, d’autant qu’on peut difficilement compter sur les fabricants, comme trop souvent encore. Malgré tout c’est fonctionnel, ce qui est déjà une première étape.

Mais comment ça pourrait aller mieux, alors qu’on annonce des « Always connected PCs » embarquant des modems 4G, voire carrément des puces ARM, Microsoft avançant main dans la main avec Qualcomm et adaptant Windows 10 pour qu’il fonctionne de manière transparente sur une plateforme non x86 ? Avec un Qualcomm en plus pas le plus respectueux en termes de support étendu de son matériel (plusieurs puces à destination d’Android ont vu leur support arrêté très rapidement, genre moins de trois ans, donc pas de possibilité propre d’exploiter les versions récentes d’Android), c’est une fois de plus une catégorie de matériel qu’il ne sera pas possible de libérer, même partiellement, d’autant plus si les outils pour l’exploiter derrière sont aussi rugueux.

Enfin bon, dans mon cas, ma mère va enfin pouvoir continuer de surfer, de mater ses vidéos sur YouTube, voire même maintenant goûter aux joies de Netflix et d’Amazon Prime Video, étant donné la qualité de plus en plus douteuse des contenus des chaînes de télévision classique, même spécialisées (et avec les rediffusions, même Science et Vie TV, ça devient chiant, je sais j’ai mangé pendant deux semaines). Bref, un usage post-2010 classique qui est encore refusé à un nombre beaucoup trop important de personnes dans notre pays en raison de choix stratégiques plus que douteux, aussi bien de la part de l’État que des acteurs privés…

 

Nethogs, un petit utilitaire sous Linux pour savoir qui consomme (consume ?) votre réseau

jeudi 28 décembre 2017 à 18:30

Actuellement en vacances chez ma petite sœur en Bretagne, à 4 (ma sœur, mon beau-frère, Arowan et moi) sur une connexion qui oscille entre 1 et 1,5 Mbps (bienvenue dans le monde réel), chaque octet qui entre ou sort d’un appareil compte, et les jonglages et arbitrages sont nombreux pour savoir qui peut regarder plus qu’une page de texte brute, ou jouer en mode déconnecté à un titre de sa collection Steam. Étant face à une étrangeté passagère où je voyais mon laptop utiliser les 140ko/s disponibles sans savoir quel processus était responsable, j’ai cherché des solutions, et j’en ai trouvé une fort sympathique.

iftop ne suffit pas toujours

J’ai déjà évoqué iftop dans un article qui commence à dater, mais toujours d’actualité. En effet, si tant est que la connexion responsable, si elle est seule, n’est pas spécialement parlante, même avec le reverse DNS. C’est ce qui s’est passé pour moi, et le whois de l’IP ne m’a pas non plus éclairé (un hébergeur du Royaume-Uni, cinquante raisons pour s’y connecter).

Nethogs à la rescousse

En effet, ce programme est salvateur. Apparemment présent partout (Debian et Manjaro vérifiés, les autres certainement), ce petit utilitaire vous affiche tous les processus lancés avec leur consommation de bande passante, ainsi que leur PID. Libre à vous ensuite de prendre une décision. Avec les options de base, ça donne ça :

Les options sont peu nombreuses, mais peuvent avoir leur utilité. Au lancement, vous pouvez changer la fréquence de rafraîchissement. Pas forcément utile sur un poste de travail, d’autant plus s’il est mobile, mais sur un serveur où les applications sont « stables », pour avoir des statistiques détaillées sur une journée par exemple, ça peut le faire. Une fois lancé, la touche m permet de changer l’unité, en KB (kilooctets) par défaut, pratique pour les grosses connexions qu’on passera en MB (mégaoctets).

Pour le reste, je vous laisse lire la documentation. Dans mon cas, et je n’ai pas pris le temps de faire de capture sur l’instant, j’ai découvert que c’était pamac qui mettait à jour les miroirs en tâche de fond, donc conso CPU limitée mais réseau à fond.

Sur ce, je retourne à mes vacances (y’a une rencontre avec Julien de computerz.solutions en vue), et je vous dis à l’année prochaine pour de nouvelles aventures en vous souhaitant de bonnes fêtes de fin d’année, même si Noël est déjà passé 🙂

Planifier une action via cron dans un container Docker

mardi 26 décembre 2017 à 18:30

Lors de la transformation de l’installation de ma forge personnelle pour la passer sous Docker Swarm, j’ai développé un petit script python pour gérer la mise à jour du sous-domaine de connexion SSH. Mon besoin était simple, donc l’exécution régulière est directement gérée dans le script, mais cette solution pratique manque cruellement de souplesse quand on veut passer à quelque chose de plus fin et complexe. Voyons comment faire plus puissant, sans que ça ne soit horriblement compliqué.

Dans le monde traditionnel de l’informatique, on imagine sans mal aussi bien sous Windows (tâches planifiées) que Linux (cron mon amour), les solutions pour planifier l’exécution de tâches à intervalles plus ou moins régulier (du style, du lundi au vendredi entre 8h et 18h). Mais quand votre service tourne sous Docker, à fortiori sous Docker Swarm, c’est fini, et l’exécution doit passer par d’autres moyens.

Rapide, simple, limité : inclus dans le service

Mon service consiste en un script Python unique, qui tourne en boucle infinie, avec une pause d’une minute à chaque fois. C’est bien, mais pour appliquer la plage d’horaire d’exécution que j’ai mis en exemple juste au dessus, c’est violent à écrire en Python et ne se résume plus dès lors à un sleep(60).

Mais techniquement, vous pouvez appliquer cette méthode à tous les langages qui vous permettent de faire des boucles, donc ça reste valable selon moi pour un besoin très basique.

Cron, mais pas avec la méthode habituelle

Je remercie à Djerfy d’avoir utilisé cette astuce qui a piqué ma curiosité. Pour un bot qui nous envoie régulièrement des citations du site Chuck Norris Facts, c’est via cron que le script qui concerne la connexion à l’API et l’envoi de la citation sur le channel Telegram est exécuté. Cela demande un peu plus de boulot par contre. Il faut plusieurs informations et commandes dans plusieurs fichiers, à commencer par la définition de la stack :

environment:
            - "CRON_SCHEDULE=30 09 * * *"

On retrouve le format habituel des tâches cron (minutes, heures, jour, mois, jour de la semaine), ce qui nous donnera des possibilités bien plus nombreuses. Le Dockerfile rajoute ensuite deux fichiers au lieu d’un seul :

RUN chmod +x /app/chucknorris.py && \
    chmod +x /app/init.sh

CMD ["/app/init.sh"]

Ce n’est donc plus le fichier python qui est appelé directement, mais init.sh. Que contient ce fichier ? Plusieurs choses, mais pour ce qui nous intéresse, voici les morceaux de choix :

if [ -z "${CRON_SCHEDULE}" ]; then
    echo -ne "Empty CRON_SCHEDULE variable\n"
    exit 1
fi

# variables crond
STDOUT_LOC=${STDOUT_LOC:-/proc/1/fd/1}
STDERR_LOC=${STDERR_LOC:-/proc/1/fd/2}

# settings crond
echo -ne "# custom script for sending jokes\n${CRON_SCHEDULE} /app/chucknorris.py > ${STDOUT_LOC} 2> ${STDERR_LOC}\n" | crontab -

# run cron
su -c "/usr/sbin/crond -f"

Mais qu’est-ce que ça fait ce morceau de code ? Pour rappel, contrairement à un système Linux classique, le processus avec le PID 1 dans un conteneur Docker est le processus lancé par la dernière commande CMD du Dockerfile, ici init.sh du coup. Dans ce script, au delà d’une vérification de base, les deux premières lignes intéressantes concernent la définition de variables concernant les descripteurs de fichier pour le fameux processus 1; en gros, on peut rediriger les sorties standards et d’erreurs vers ces descripteurs, ce qui permet de visualiser les messages de notre application réelle via les commandes Docker sur l’hôte.

Ensuite, on définit un nouveau fichier de crontab avec les informations de l’environnement (c’est ce que fait le  echo |crontab -), et enfin on lance crond. Mais que fait donc le -f ? Au début, en fouillant « bêtement » le manuel de crond, je ne trouve pas trace du -f en question, mais c’est le cas dans le manuel de cron. Le switch -f indique à cron de rester en premier plan (foreground, pour les anglophiles qui se poseraient la question), et non de passer en mode démon, ce qui est une condition sine qua non sur le PID 1 pour qu’un container Docker reste en vie.

La puissance de Cron, avec ses faiblesses

J’imagine qu’il faudra un peu plus de boulot si vous devez intégrer plusieurs tâches planifiées dans le même container. On sera probablement plus avisé de séparer les tâches dans des containers séparés si ça concerne des scripts différents.

Cron n’est pas non plus la solution la plus parfaite, et j’ai déjà buté ou été obligé de bricoler (parfois dans le script lancé lui-même), pour obtenir le résultat que voulait le client. En gros, ça ne fait rien de plus ni de moins qu’un service cron sur un OS classique, mais ça permet déjà bien plus de possibilités que d’écrire et de conditionner en dur les exécutions de votre tâche.