<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Normal sur Olivier DOSSMANN</title>
    <link>https://olivier.dossmann.net/categories/normal/</link>
    <description>Contenu récent dans Normal sur Olivier DOSSMANN</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>fr</language>
    <copyright>© 2014-2022 Olivier DOSSMANN</copyright>
    <lastBuildDate>Sun, 22 Mar 2026 11:42:00 +0100</lastBuildDate><atom:link href="https://olivier.dossmann.net/categories/normal/index.xml" rel="self" type="application/rss+xml" />
    <item>
	    <title>Encore un autre lecteur de flux RSS, Yarr</title>
      <link>https://olivier.dossmann.net/2026/03/encore-un-autre-lecteur-de-flux-rss-yarr/</link>
      <pubDate>Sun, 22 Mar 2026 11:42:00 +0100</pubDate>
      
      <guid>https://olivier.dossmann.net/2026/03/encore-un-autre-lecteur-de-flux-rss-yarr/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Il y a fort fort longtemps (en 2009), je testais &lt;a href=&#34;https://tt-rss.org/&#34;&gt;&lt;strong&gt;TinyTinyRSS&lt;/strong&gt;, un lecteur de flux RSS&lt;/a&gt; avec une interface Web. J&amp;rsquo;en parlais d&amp;rsquo;ailleurs dans un &lt;a href=&#34;https://olivier.dossmann.net/2009/09/nouvelles-astuces-sur-rxvt-unicode-et-tinytinyrss/&#34; title=&#34;Découvrir mon article sur TinyTinyRSS et rxvt-unicode&#34;&gt;article pour signaler la venue de deux nouveaux tutoriels (dont TinyTinyRSS) dans mon Recueil d&amp;rsquo;astuces&lt;/a&gt;. Ce lecteur était &lt;strong&gt;agréable à l&amp;rsquo;usage, rapide&lt;/strong&gt; et utilisait une base de données &lt;strong&gt;postgreSQL&lt;/strong&gt;. Bref, tout ce que je voulais à l&amp;rsquo;époque. Le temps a passé ; je dépensais moins de temps sur les flux RSS. Puis j&amp;rsquo;ai arrêté - qu&amp;rsquo;importe les raisons. Ça fait &lt;strong&gt;bientôt 10 ans&lt;/strong&gt; que j&amp;rsquo;ai laissé cela derrière moi.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Bouh la honte Olivier !&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Certes.&lt;/p&gt;
&lt;p&gt;Récemment, &lt;strong&gt;une mouche m&amp;rsquo;a piquée&lt;/strong&gt; - ou une &lt;em&gt;lubie&lt;/em&gt; - et &lt;strong&gt;je me suis renseigné&lt;/strong&gt; sur les outils de lecture de &lt;strong&gt;flux RSS&lt;/strong&gt; façon &lt;strong&gt;auto-hébergés et minimalistes&lt;/strong&gt;. Je ne vais pas détailler la liste dans cet article puisque, vous l&amp;rsquo;aurez compris, on parle déjà dans le titre de &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;&lt;strong&gt;Yarr&lt;/strong&gt;&lt;/a&gt; !&lt;/p&gt;
&lt;p&gt;Ainsi nous commencerons par présenter l&amp;rsquo;outil, pour ensuite décrire comment l&amp;rsquo;utiliser avec docker-compose pour finalement terminer par mon retour d&amp;rsquo;expérience après quelques jours d&amp;rsquo;utilisation (démarrage au 25 février 2026) et via un &lt;strong&gt;tour complet de l&amp;rsquo;outil&lt;/strong&gt; - ça va être long mais il y a des images &amp;#x1f609; .&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/objets/faisceaux_lumineux.jpg&#34; alt=&#34;Image de faisceaux lumineux multiples qui ont sûrement dérivé&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://www.flickr.com/photos/12836528@N00/&#34;&gt;profil de Kevin Dooley sur Flickr&lt;/a&gt;&lt;/em&gt; sous licence CC BY 2.0.&lt;/p&gt;
&lt;h1 id=&#34;découverte-de-yarr&#34;&gt;Découverte de Yarr&lt;/h1&gt;
&lt;p&gt;Avant de découvrir : &lt;strong&gt;on cherche&lt;/strong&gt; ! J&amp;rsquo;ai donc établi une petite liste de &lt;strong&gt;critères pour la recherche d&amp;rsquo;un lecteur de flux RSS&lt;/strong&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;simple, voire &lt;strong&gt;basique&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;avec une &lt;strong&gt;interface Web&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;auto-hébergeable&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open Source&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rapide&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;léger&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;sans forcément une base de données de type MySQL ou PostgreSQL. SQLite acceptable,&lt;/li&gt;
&lt;li&gt;écrit, éventuellement, &lt;strong&gt;en Go&lt;/strong&gt; (j&amp;rsquo;envisage d&amp;rsquo;apprendre prochainement le Go).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;ai donc cherché. J&amp;rsquo;ai trouvé quelques outils comme :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://miniflux.app/&#34;&gt;Miniflux&lt;/a&gt; (en Go),&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://freshrss.org/index.html&#34;&gt;FreshRSS&lt;/a&gt; (en PHP),&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/LeedRSS/Leed&#34;&gt;LeedRSS&lt;/a&gt; (en PHP),&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ncarlier/feedpushr&#34;&gt;feedpushr&lt;/a&gt; (en Go),&lt;/li&gt;
&lt;li&gt;et &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt; (en Go).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je l&amp;rsquo;ai déjà annoncé : nous n&amp;rsquo;irons pas plus loin avec cette liste.&lt;/p&gt;
&lt;p&gt;Nul besoin de faire la promotion de &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;, je pense qu&amp;rsquo;&lt;a href=&#34;https://lord.re/posts/246-yarr-web-rss-pour-remplacer-ttrss/&#34;&gt;Internet fait déjà de belles suggestions d&amp;rsquo;utilisation de Yarr comme remplaçant de TinyTinyRSS&lt;/a&gt;. Petite histoire marrante : le nom est l&amp;rsquo;&lt;strong&gt;acronyme de Yet Another Rss Reader&lt;/strong&gt;, littéralement « Encore un autre lecteur RSS » ou « L&amp;rsquo;énième lecteur de flux RSS ».&lt;/p&gt;
&lt;p&gt;Une fois cette lecture de blog effectuée, j&amp;rsquo;ai voulu tester &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;. Je me suis donc lancé dans l&amp;rsquo;écriture d&amp;rsquo;un fichier &lt;strong&gt;docker-compose.yml&lt;/strong&gt;.&lt;/p&gt;
&lt;h1 id=&#34;mon-fichier-docker-composeyaml-pour-yarr&#34;&gt;Mon fichier docker-compose.yaml pour Yarr&lt;/h1&gt;
&lt;p&gt;Il aura fallu &lt;strong&gt;moins de 20 minutes&lt;/strong&gt; pour trouver l&amp;rsquo;image Docker de &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt; sur le &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;dépôt officiel de Yarr sur Github&lt;/a&gt;. Cependant l&amp;rsquo;image étant sur Github Actions - que je connais peu - j&amp;rsquo;ai eu plus de mal à trouver le nom donné à l&amp;rsquo;image pour la récupérer depuis Docker. Je vous le donne de suite : &lt;strong&gt;ghcr.io/nkanaev/yarr:v2.5&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Une fois le nom de l&amp;rsquo;image obtenu, il reste à en connaître son usage. Heureusement j&amp;rsquo;ai trouvé un article sur la création d&amp;rsquo;un fichier docker-compose.yaml pour &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt; (Cf. &lt;a href=&#34;https://awesome-docker-compose.com/apps/rss/yarr&#34;&gt;https://awesome-docker-compose.com/apps/rss/yarr&lt;/a&gt;) dont je me suis, forcément, grandement inspiré. Et oui je le dis quand j&amp;rsquo;utilise quelque chose qui n&amp;rsquo;est pas de moi &amp;#x1f609; .&lt;/p&gt;
&lt;p&gt;Ainsi j&amp;rsquo;ai pu construire le fichier &lt;strong&gt;docker-compose.yaml&lt;/strong&gt; suivant :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;yarr&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ghcr.io/nkanaev/yarr:v2.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;yarr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;7070&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;${DATA_DIR:-./data}:/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;command&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - --&lt;span style=&#34;color:#ae81ff&#34;&gt;addr=0.0.0.0:7070&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - --&lt;span style=&#34;color:#ae81ff&#34;&gt;db=/data/yarr.db&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - --&lt;span style=&#34;color:#ae81ff&#34;&gt;auth=${Y_USER}:${PASSWORD}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;TZ=Europe/Paris&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.enable=true&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.${SERVICE}.rule=Host(`$DOMAIN_URL`)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.${SERVICE}.entrypoints=websecure&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;où :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DATA_DIR&lt;/strong&gt;, &lt;strong&gt;Y_USER&lt;/strong&gt;, &lt;strong&gt;PASSWORD&lt;/strong&gt;, &lt;strong&gt;SERVICE&lt;/strong&gt; et &lt;strong&gt;DOMAIN_URL&lt;/strong&gt; sont à renseigner dans un fichier &lt;em&gt;.env&lt;/em&gt; (avec une valeur),&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DATA_DIR&lt;/strong&gt; est le chemin vers le point de montage où seront stockées les données de &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Y_USER&lt;/strong&gt; est le nom d&amp;rsquo;utilisateur que vous souhaitez utiliser comme &lt;em&gt;login&lt;/em&gt; pour s&amp;rsquo;identifier sur votre &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PASSWORD&lt;/strong&gt;… bah le mot de passe pour s&amp;rsquo;identifier au service &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SERVICE&lt;/strong&gt; est un nom (en minuscule, sans espace et sans point) pour le routeur dans Træfik (si vous n&amp;rsquo;utilisez pas Træfik, supprimez la section &amp;ldquo;labels&amp;rdquo; de ce docker-compose.yaml),&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DOMAIN_URL&lt;/strong&gt; est l&amp;rsquo;adresse web pour accéder au service, mais seulement si vous utilisez Træfik en frontal. Sinon supprimez la section &amp;ldquo;labels&amp;rdquo; de ce fichier docker-compose.yaml.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Exemple de fichier &lt;em&gt;.env&lt;/em&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;SERVICE&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;monService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DOMAIN_URL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;domain.tld&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DATA_DIR&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/srv/http/yarr_data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Y_USER&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;olivier&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;PASSWORD&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;mot2passe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vous noterez qu&amp;rsquo;on &lt;strong&gt;autorise&lt;/strong&gt; volontairement &lt;strong&gt;toutes les IP&lt;/strong&gt; pour accéder au service (0.0.0.0). Ce dernier s&amp;rsquo;ouvrira sur le &lt;strong&gt;port 7070&lt;/strong&gt; dans le conteneur, mais Docker choisira un port aléatoire sur ce service (pour éviter de demander un port déjà utilisé). Nous en parlerons ci-après avec la commande &lt;code&gt;docker compose port&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Une fois le fichier &lt;em&gt;.env&lt;/em&gt; configuré, on lance et accède rapidement au service (pour tester par exemple) :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Lance le service en arrière plan - récupération de la main sur l&amp;#39;invite de commande&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Affiche les conteneurs lancés&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker compose ps
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Affiche l&amp;#39;adresse pour accéder au service en local&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker compose port yarr &lt;span style=&#34;color:#ae81ff&#34;&gt;7070&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On lance un navigateur, on tape l&amp;rsquo;adresse retournée par la dernière commande (chez moi &lt;strong&gt;0.0.0.0:32768&lt;/strong&gt;) et le lecteur de flux RSS apparaît. C&amp;rsquo;est parti pour une période d&amp;rsquo;essai de plusieurs jours (tests commencés à partir du 25 février 2026).&lt;/p&gt;
&lt;h1 id=&#34;mon-expérience-avec-yarr---on-fait-le-tour&#34;&gt;Mon expérience avec Yarr - on fait le tour !&lt;/h1&gt;
&lt;h2 id=&#34;lauthentification&#34;&gt;L&amp;rsquo;authentification&lt;/h2&gt;
&lt;p&gt;Dans le fichier docker-compose.yml précédent nous avons ajouté l&amp;rsquo;option &lt;code&gt;--auth&lt;/code&gt; afin d&amp;rsquo;activer l&amp;rsquo;authentification de &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;. La &lt;strong&gt;première page&lt;/strong&gt; sur laquelle nous tombons est donc celle &lt;strong&gt;pour s&amp;rsquo;identifier&lt;/strong&gt; :&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/logiciels/yarr_accueil.png&#34; alt=&#34;Formulaire d&amp;rsquo;accueil pour s&amp;rsquo;identifier&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Simple&lt;/strong&gt;, efficace.&lt;/p&gt;
&lt;h2 id=&#34;linterface-générale&#34;&gt;L&amp;rsquo;interface générale&lt;/h2&gt;
&lt;p&gt;L&amp;rsquo;accueil est plutôt &lt;strong&gt;austère&lt;/strong&gt; - chouette c&amp;rsquo;est &lt;strong&gt;ce que je voulais&lt;/strong&gt; ! - et propose une &lt;strong&gt;disposition en 3 colonnes&lt;/strong&gt; :&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/logiciels/yarr_3_colonnes.png&#34; alt=&#34;Disposition en 3 colonnes sur la page d&amp;rsquo;accueil de Yarr&#34;&gt;&lt;/p&gt;
&lt;p&gt;Chaque colonne sert un objectif précis, de gauche à droite :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la &lt;strong&gt;liste des flux&lt;/strong&gt; RSS,&lt;/li&gt;
&lt;li&gt;puis la &lt;strong&gt;liste des articles&lt;/strong&gt;/éléments d&amp;rsquo;un flux en particulier,&lt;/li&gt;
&lt;li&gt;puis &lt;strong&gt;l&amp;rsquo;article&lt;/strong&gt; choisi parmi la liste précédente.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Donc plus on se dirige à droite, plus la lecture se précise.&lt;/p&gt;
&lt;p&gt;Sur téléphone mobile il n&amp;rsquo;y aura plus qu&amp;rsquo;une seule colonne : celle tout à gauche. On choisira ainsi un flux, ce qui affichera la liste des articles et si on choisit un article, on verra son contenu. Toujours sur une colonne. &lt;strong&gt;Astucieux&lt;/strong&gt;, &lt;strong&gt;logique&lt;/strong&gt; et presque &lt;strong&gt;intuitif&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;avoue que sur ce dernier point, sur téléphone mobile, j&amp;rsquo;ai été totalement perdu : je ne savais pas où j&amp;rsquo;étais et ce que je faisais. Ce n&amp;rsquo;est qu&amp;rsquo;en comparant l&amp;rsquo;usage entre un grand écran et un petit écran que j&amp;rsquo;ai saisi ce qu&amp;rsquo;il en était. Sur ce coup-là, je suis le couteau le moins aiguisé du tiroir…&lt;/p&gt;
&lt;h2 id=&#34;la-configuration-de-linterface&#34;&gt;La configuration de l&amp;rsquo;interface&lt;/h2&gt;
&lt;p&gt;Je continue ma découverte avec l&amp;rsquo;&lt;strong&gt;icône représentant 3 petits points&lt;/strong&gt; en haut à droite de la première colonne (ou en haut à droite sur un petit écran ne présentant donc qu&amp;rsquo;une seule colonne). Les options de l&amp;rsquo;outil apparaissent :&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/logiciels/yarr_options.png&#34; alt=&#34;Image contenant le menu d&amp;rsquo;option de configuration de l&amp;rsquo;outil Yarr&#34;&gt;&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est ici que va se jouer les &lt;strong&gt;seules options disponibles dans &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;&lt;/strong&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New Feed&lt;/strong&gt; : Permet d&amp;rsquo;&lt;strong&gt;ajouter un nouveau flux&lt;/strong&gt;. Il faut 2 infos : l&amp;rsquo;adresse URL du flux, et le dossier dans lequel le ranger,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Refresh Feeds&lt;/strong&gt; : &lt;strong&gt;Actualisation&lt;/strong&gt; des flux,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Theme&lt;/strong&gt; : Pour changer l&amp;rsquo;&lt;strong&gt;apparence de &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;&lt;/strong&gt;. Nous en parlerons tout à l&amp;rsquo;heure,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto Refresh&lt;/strong&gt; : Permet de choisir le &lt;strong&gt;laps de temps&lt;/strong&gt; entre plusieurs &lt;strong&gt;rafraîchissements automatiques&lt;/strong&gt;. Comprendre : on récupère les flux tous les X temps (de 0mn à 4h),&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Show first&lt;/strong&gt; : Permet de choisir si on préfère afficher les &lt;strong&gt;articles parus récemment&lt;/strong&gt; en premier (&lt;em&gt;New&lt;/em&gt;) &lt;strong&gt;ou ceux les plus anciens&lt;/strong&gt; en premier (&lt;em&gt;Old&lt;/em&gt;),&lt;/li&gt;
&lt;li&gt;Subscriptions :
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Import&lt;/strong&gt; : Donne la possibilité d&amp;rsquo;importer une liste de flux (au &lt;strong&gt;format OPML&lt;/strong&gt;),&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Export&lt;/strong&gt; : Permet d&amp;rsquo;exporter sa liste de flux (au &lt;strong&gt;format OPML&lt;/strong&gt;) pour la partager par exemple,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shortcuts&lt;/strong&gt; : Affiche un rappel des &lt;strong&gt;raccourcis claviers&lt;/strong&gt; possibles pour naviguer et lire les flux. Et ils sont &lt;strong&gt;très utiles&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Log out&lt;/strong&gt; : Apparaîtra seulement si l&amp;rsquo;option &lt;code&gt;--auth&lt;/code&gt; a été utilisée. C&amp;rsquo;est pour &lt;strong&gt;se déconnecter&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;avais peur de tomber sur un lecteur avec des milliers de configurations. Finalement &lt;strong&gt;&lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt; va à l&amp;rsquo;essentiel&lt;/strong&gt;. Cela me plaît - encore une fois.&lt;/p&gt;
&lt;h2 id=&#34;choix-dun-thème&#34;&gt;Choix d&amp;rsquo;un thème&lt;/h2&gt;
&lt;p&gt;Vous aurez remarqué que &lt;strong&gt;mes impressions écrans&lt;/strong&gt; présentent les pages d&amp;rsquo;une &lt;strong&gt;couleur simili jaune&lt;/strong&gt; (qui fait penser à &lt;a href=&#34;https://ethanschoonover.com/solarized/&#34;&gt;Solarized Light d&amp;rsquo;Ethan Shoonover&lt;/a&gt;). C&amp;rsquo;est parce que j&amp;rsquo;ai choisi un thème. On peut &lt;strong&gt;choisir entre 3 thèmes&lt;/strong&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;blanc&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;jaune&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;noir&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je suis content du thème jaune car ma vue pose problème avec les thèmes noirs (l&amp;rsquo;astigmathie a une forme d&amp;rsquo;opposition rebelle au &amp;ldquo;dark theme&amp;rdquo; et peut rendre les textes &amp;ldquo;flous&amp;rdquo;). Certes, la &lt;a href=&#34;https://www.nngroup.com/articles/dark-mode/&#34;&gt;performance de lecture est plus importante en mode &amp;ldquo;light&amp;rdquo;&lt;/a&gt;, mais ça reste trop lumineux pour moi. Je n&amp;rsquo;aime pas le jaune en tant que tel, mais pour mon efficacité de lecture c&amp;rsquo;est le &amp;ldquo;moins pire&amp;rdquo; &amp;#x1f923; . Évidemment les tendances s&amp;rsquo;inversent la nuit (mais pas pour moi), dans la pénombre et/ou dans un environnement peu lumineux. Mais nous ne sommes pas ici pour lancer le troll « Dark Mode vs. Light Mode », ou bien ? Combat !&lt;/p&gt;
&lt;h2 id=&#34;les-trois-icônes-principales&#34;&gt;Les trois icônes principales&lt;/h2&gt;
&lt;p&gt;Vous avez découvert l&amp;rsquo;usage en 3 colonnes, cette fois nous allons découvrir l&amp;rsquo;usage des 3 icônes tout en haut qui sont, en quelque sorte, le menu principal de &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un rond rempli de noir,&lt;/li&gt;
&lt;li&gt;une étoile,&lt;/li&gt;
&lt;li&gt;3 traits horizontaux parallèles de longueurs différentes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La première (le &lt;strong&gt;rond noir&lt;/strong&gt;) permet d&amp;rsquo;&lt;strong&gt;afficher la liste des flux&lt;/strong&gt; sur lesquels nous avons encore des articles/éléments à lire.&lt;/p&gt;
&lt;p&gt;La seconde (&lt;strong&gt;étoile noire&lt;/strong&gt;) affiche une liste des flux sur lequels vous avez marqués des articles/éléments comme &lt;strong&gt;favoris&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Et la dernière (les &lt;strong&gt;3 traits horizontaux&lt;/strong&gt;) affiche la &lt;strong&gt;liste complète des flux&lt;/strong&gt;, qu&amp;rsquo;importe qu&amp;rsquo;il vous reste ou non des articles/éléments à lire.&lt;/p&gt;
&lt;p&gt;Exemple d&amp;rsquo;affichage en 3 colonnes sur le rond noir avec le choix d&amp;rsquo;un article et son affichage :&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/logiciels/yarr_exemple.png&#34; alt=&#34;Affichage en 3 colonnes de Yarr avec le choix du flux MiniMachines.net, d&amp;rsquo;un article précis et de son affichage dans la dernière colonne&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Simple, basique, sans fioritures&lt;/strong&gt;. Utilisable &lt;strong&gt;avec des raccourcis&lt;/strong&gt; clavier. &lt;strong&gt;Parfait&lt;/strong&gt; !&lt;/p&gt;
&lt;h2 id=&#34;les-derniers-petits-détails---et-après-jarrête-promis&#34;&gt;Les derniers petits détails - et après j&amp;rsquo;arrête promis !&lt;/h2&gt;
&lt;p&gt;Dernière liste d&amp;rsquo;icônes dans l&amp;rsquo;interface :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;deuxième colonne :
&lt;ul&gt;
&lt;li&gt;icône de &lt;strong&gt;loupe&lt;/strong&gt; : Fait une &lt;strong&gt;recherche dans la liste d&amp;rsquo;article&lt;/strong&gt; de &lt;strong&gt;CE&lt;/strong&gt; flux choisi,&lt;/li&gt;
&lt;li&gt;icône de &lt;strong&gt;validation&lt;/strong&gt; : &lt;strong&gt;Marque tous les articles&lt;/strong&gt; de ce flux &lt;strong&gt;comme lus&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;icône de &lt;strong&gt;3 petits points&lt;/strong&gt; l&amp;rsquo;un à côté de l&amp;rsquo;autre verticalement : c&amp;rsquo;est ici qu&amp;rsquo;on a les &lt;strong&gt;détails du flux&lt;/strong&gt;. On peut le renommer, le changer de place, le supprimer, aller sur le site Web, etc.,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;troisième colonne :
&lt;ul&gt;
&lt;li&gt;icône d&amp;rsquo;&lt;strong&gt;étoile&lt;/strong&gt; (vide/remplie) : Marque l&amp;rsquo;article en &lt;strong&gt;favori&lt;/strong&gt; ou au contraire l&amp;rsquo;enlève des favoris,&lt;/li&gt;
&lt;li&gt;icône d&amp;rsquo;un &lt;strong&gt;rond&lt;/strong&gt; (vide/rempli) : Marque l&amp;rsquo;article comme &lt;strong&gt;lu ou non-lu&lt;/strong&gt; (suivant de quel état on commence),&lt;/li&gt;
&lt;li&gt;icône de &lt;strong&gt;traits verticaux entrecoupés comme de petits pistons&lt;/strong&gt; : Permet de &lt;strong&gt;changer la police&lt;/strong&gt; d&amp;rsquo;écriture (parmi sans-serif, serif et monospace) ainsi que &lt;strong&gt;la taille de police&lt;/strong&gt; (petit, ou grand, plus on appuie plus ça réduit/aggrandit),&lt;/li&gt;
&lt;li&gt;icône d&amp;rsquo;un &lt;strong&gt;livre ouvert&lt;/strong&gt; : Choisi de &lt;strong&gt;lire l&amp;rsquo;article dans &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;&lt;/strong&gt; ou bien seulement les informations du flux RSS,&lt;/li&gt;
&lt;li&gt;icône d&amp;rsquo;un &lt;strong&gt;carré avec une flèche qui en sort&lt;/strong&gt;) : Va &lt;strong&gt;directement sur le site Web de l&amp;rsquo;article&lt;/strong&gt; en question.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/logiciels/yarr_flux_options.png&#34; alt=&#34;Détail des options disponible pour un flux donné dans la seconde colonne sur l&amp;rsquo;icône avec les 3 petits points&#34;&gt;&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;utilise souvent l&amp;rsquo;icône de validation de la seconde colonne pour marquer tous les articles comme lus une fois que j&amp;rsquo;ai parcouru la liste des titres et que rien ne m&amp;rsquo;intéressait.&lt;/p&gt;
&lt;p&gt;Les raccourcis claviers sont là pour faciliter le traitement des articles (lu, non-lu, favori, lire à l&amp;rsquo;extérieur, etc.). Parfois j&amp;rsquo;utilise le raccourci &amp;ldquo;o&amp;rdquo; pour lire l&amp;rsquo;article sur le site Web.&lt;/p&gt;
&lt;p&gt;Du reste, je n&amp;rsquo;utilise quasiment rien. Après tout je ne viens que pour lire des titres, trier et lire un article de temps en temps &amp;#x1f937; . Je ne suis pas là pour bosser.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Au début &lt;strong&gt;un peu perdu par l&amp;rsquo;interface&lt;/strong&gt; afin de &lt;strong&gt;comprendre à quoi sert chaque élément&lt;/strong&gt; - surtout entre interface petit écran et grand écran - j&amp;rsquo;ai finalement &lt;strong&gt;apprécié &lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt; à l&amp;rsquo;usage&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est un outil &amp;ldquo;menu&amp;rdquo; (maigre, &lt;strong&gt;léger&lt;/strong&gt;), simple, &lt;strong&gt;basique, sans fioritures&lt;/strong&gt;. &lt;strong&gt;Configurable&lt;/strong&gt; un minimum. Utilisable avec des &lt;strong&gt;raccourcis clavier&lt;/strong&gt;. Très efficace d&amp;rsquo;ailleurs avec un clavier quand on s&amp;rsquo;y fait. C&amp;rsquo;est même redoutable de rapidité quand on a le coup de main !&lt;/p&gt;
&lt;p&gt;À vrai dire, je ne sais même pas de quoi j&amp;rsquo;aurais besoin en plus pour lire des flux. J&amp;rsquo;ajoute rapidement des flux, j&amp;rsquo;&lt;strong&gt;importe et exporte facilement&lt;/strong&gt; pour partager avec d&amp;rsquo;autres, je vois de nouveaux articles, je clique sur ce qui m&amp;rsquo;intéresse, je lis, je note le reste des articles comme lus pour ce flux et voilà.&lt;/p&gt;
&lt;p&gt;Ni plus. Ni moins. &lt;strong&gt;Parfait&lt;/strong&gt; &amp;#x1f604; .&lt;/p&gt;
&lt;h1 id=&#34;liens-utiles&#34;&gt;Liens utiles&lt;/h1&gt;
&lt;p&gt;Voici les liens de l&amp;rsquo;article par ordre d&amp;rsquo;apparition :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://tt-rss.org/&#34;&gt;TinyTinyRSS, un lecteur de flux RSS&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://olivier.dossmann.net/2009/09/nouvelles-astuces-sur-rxvt-unicode-et-tinytinyrss/&#34;&gt;Mon article pour signaler la venue de deux nouveaux tutoriels (dont TinyTinyRSS) dans mon Recueil d&amp;rsquo;astuces&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/nkanaev/yarr&#34;&gt;Yarr&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://miniflux.app/&#34;&gt;Miniflux&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://freshrss.org/index.html&#34;&gt;FreshRSS&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/LeedRSS/Leed&#34;&gt;LeedRSS&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ncarlier/feedpushr&#34;&gt;feedpushr&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://lord.re/posts/246-yarr-web-rss-pour-remplacer-ttrss/&#34;&gt;Bel article sur  l&amp;rsquo;utilisation de Yarr comme remplaçant de TinyTinyRSS&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://awesome-docker-compose.com/apps/rss/yarr&#34;&gt;Exemple de docker-compose pour Yarr&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ethanschoonover.com/solarized/&#34;&gt;Solarized Light d&amp;rsquo;Ethan Shoonover&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.nngroup.com/articles/dark-mode/&#34;&gt;La performance de lecture suivant le thème light/dark et nos yeux&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
	    <title>RustFS, alternative au service de stockage objet MinIO</title>
      <link>https://olivier.dossmann.net/2026/02/rustfs-alternative-au-service-de-stockage-objet-minio/</link>
      <pubDate>Sun, 15 Feb 2026 17:27:26 +0100</pubDate>
      
      <guid>https://olivier.dossmann.net/2026/02/rustfs-alternative-au-service-de-stockage-objet-minio/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://olivier.dossmann.net/2025/11/mon-labo-k8s-pour-essayer-des-applications/&#34;&gt;Quand on étudie &lt;strong&gt;Kubernetes&lt;/strong&gt;&lt;/a&gt;, on arrive tôt ou tard sur la question de la &lt;strong&gt;gestion des sauvegardes&lt;/strong&gt;. Et avec elles le &lt;strong&gt;sujet du stockage&lt;/strong&gt; de ces dernières. La référence en matière de sauvegarde - dont je parlerais sûrement dans un prochain article - est &lt;a href=&#34;https://velero.io/&#34;&gt;Velero&lt;/a&gt;. Cet outil supporte plusieurs fournisseurs de stockage pour ses opérations de sauvegarde comme Amazon Web Services, Google Cloud, Microsoft Azure ou VMware Sphere. Principalement des fournisseurs liés à une entreprise. Que faire dans la situation où nous souhaitons &lt;strong&gt;auto-héberger une solution de stockage&lt;/strong&gt; chez soi ?&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est ce dont je voudrais parler aujourd&amp;rsquo;hui : une solution spécifique que j&amp;rsquo;ai - presque - choisie. Surtout &lt;strong&gt;pourquoi cette solution&lt;/strong&gt; ? Je décrirais son &lt;strong&gt;installation sous Docker Compose&lt;/strong&gt; derrière un proxy nommé &lt;a href=&#34;https://olivier.dossmann.net/2022/12/utilisation-de-tr%C3%A6fik-pour-publier-ses-conteneurs-docker/&#34;&gt;Traefik, dont je vous ai déjà parlé&lt;/a&gt;. Et j&amp;rsquo;ajouterais quelques mots sur les ports réseau à ouvrir, l&amp;rsquo;&lt;strong&gt;initialisation des premiers « buckets »&lt;/strong&gt; (nous y reviendrons) et l&amp;rsquo;usage de noms de domaines.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/logos/rustfs.png&#34; alt=&#34;Logo du projet RustFS, simple écriture du mot RustFS en bleu&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;pourquoi-cette-solution&#34;&gt;Pourquoi cette solution ?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Si vous n&amp;rsquo;êtes pas fan de l&amp;rsquo;histoire&lt;/strong&gt; de « pourquoi choisir cette solution », &lt;strong&gt;vous pouvez passer au chapitre suivant&lt;/strong&gt;, je ne vous en voudrais pas &amp;#x1f609;.&lt;/p&gt;
&lt;p&gt;En étudiant &lt;a href=&#34;https://velero.io/docs/&#34;&gt;la documentation de Velero&lt;/a&gt; on découvre parmi les &lt;strong&gt;fournisseurs de solutions de stockage&lt;/strong&gt; le célèbre Amazon Web Services. Et avec lui le service &lt;strong&gt;Amazon S3&lt;/strong&gt;. Ce service est une &lt;strong&gt;solution de &lt;a href=&#34;https://fr.wikipedia.org/wiki/Stockage_objet&#34;&gt;stockage objet&lt;/a&gt;&lt;/strong&gt; qui a développé un &lt;strong&gt;protocole ouvert&lt;/strong&gt; du même nom : &lt;a href=&#34;https://fr.wikipedia.org/wiki/Amazon_S3&#34;&gt;&lt;strong&gt;S3&lt;/strong&gt;&lt;/a&gt;. Grâce à cela, de nombreux outils compatibles avec ce protocole ont vu le jour ; que ce soit des clients comme des serveurs. Top, c&amp;rsquo;est ce que je recherche !&lt;/p&gt;
&lt;p&gt;Ayant beaucoup entendu parler de &lt;strong&gt;MinIO&lt;/strong&gt;, je m&amp;rsquo;enquiers de l&amp;rsquo;installer fin novembre 2025. En Docker Compose, &lt;a href=&#34;https://olivier.dossmann.net/2022/12/utilisation-de-tr%C3%A6fik-pour-publier-ses-conteneurs-docker/&#34;&gt;derrière Traefik comme je l&amp;rsquo;explique dans un précédent article sur le sujet&lt;/a&gt;. Mais &lt;strong&gt;quelques problèmes se posent&lt;/strong&gt; successivement :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;en août 2025 les dépôts de Bitnami, qui fournissaient jusqu&amp;rsquo;alors d&amp;rsquo;excellentes images, chartes Helm et outils en tous genres sont chamboulés par &lt;a href=&#34;https://github.com/bitnami/charts/issues/35164&#34;&gt;une &lt;strong&gt;décision drastique prise par Bitnami&lt;/strong&gt;&lt;/a&gt;. L&amp;rsquo;impact est énorme sur la communauté,&lt;/li&gt;
&lt;li&gt;faute de cette image pratique, je me tourne vers l&amp;rsquo;image officielle qui demande des &lt;strong&gt;ajustements pour avoir des « buckets » à l&amp;rsquo;initialisation&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;finalement &lt;strong&gt;le 13 février 2026, l&amp;rsquo;entreprise qui gérait MinIO décide d&amp;rsquo;abandonner la maintenance&lt;/strong&gt; de la version communautaire.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Coup dur. Je recherche des alternatives. Je tombe sur le &lt;a href=&#34;https://github.com/rustfs/rustfs/issues/555#issuecomment-3620454213&#34;&gt;message de loverustfs qui compare les &lt;strong&gt;solutions alternatives&lt;/strong&gt; à RustFS, dont MinIO, Garage, Ceph, Seaweeedfs, etc.&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit (24 fév. 2026)&lt;/strong&gt; : Un &lt;a href=&#34;https://github.com/pgsty/minio&#34;&gt;fork de MinIO&lt;/a&gt; est apparu il y a quelques jours. Si le cœur vous en dit &amp;#x1f937;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/rustfs/rustfs&#34;&gt;&lt;strong&gt;RustFS&lt;/strong&gt;&lt;/a&gt; n&amp;rsquo;est probablement pas la solution la plus performante (Seaweedfs semble plus performant), mais il se défend bien. Et il semble &lt;strong&gt;proche de MinIO&lt;/strong&gt; en terme d&amp;rsquo;interface et d&amp;rsquo;utilisation. Allons donc, ne le faisons pas attendre, installons-le !&lt;/p&gt;
&lt;h1 id=&#34;rustfs-sous-docker-compose&#34;&gt;RustFS sous Docker Compose&lt;/h1&gt;
&lt;p&gt;L&amp;rsquo;idée est d&amp;rsquo;installer/utiliser &lt;strong&gt;RustFS avec Docker Compose&lt;/strong&gt;. Derrière &lt;strong&gt;Træfik&lt;/strong&gt;. Avec des domaines.&lt;/p&gt;
&lt;h2 id=&#34;installation-minimale&#34;&gt;Installation minimale&lt;/h2&gt;
&lt;p&gt;On commence par une installation de base. On a besoin de :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;une &lt;strong&gt;image Docker&lt;/strong&gt;. Ça tombe bien, il y a des &lt;a href=&#34;https://hub.docker.com/r/rustfs/rustfs&#34;&gt;images officielles de RustFS sur le Hub Docker&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;ouvrir &lt;strong&gt;2 ports&lt;/strong&gt; :
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;9000&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;9001&lt;/strong&gt;,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;un volume local&lt;/strong&gt; pour stocker les données et pouvoir les réutiliser entre 2 redémarrages de conteneurs,&lt;/li&gt;
&lt;li&gt;un &lt;strong&gt;identifiant&lt;/strong&gt; et un &lt;strong&gt;mot de passe&lt;/strong&gt; initial.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;ATTENTION&lt;/strong&gt; : le projet &lt;strong&gt;RustFS est encore jeune&lt;/strong&gt;, il est en développement actif et les versions ne sont pas toutes utilisables telles quelles. Par exemple dans ma situation, la &lt;em&gt;version 1.0.0-alpha.83&lt;/em&gt; était inutilisable. Ceci dû à un &lt;a href=&#34;https://github.com/rustfs/rustfs/issues/1838&#34;&gt;bug sur l&amp;rsquo;architecture de ma machine comme le montre ce ticket Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Une première ébauche d&amp;rsquo;un fichier docker-compose.yaml pourrait s&amp;rsquo;écrire de la manière suivante :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;rustfs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rustfs/rustfs:1.0.0-alpha.82&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;9001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;./storage_data:/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;/etc/timezone:/etc/timezone:ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_VOLUMES=/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_ADDRESS=0.0.0.0:9000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_CONSOLE_ADDRESS=0.0.0.0:9001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_CONSOLE_ENABLE=true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_ACCESS_KEY=olivier&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_SECRET_KEY=mot2passe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_OBS_LOGGER_LEVEL=info&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;healthcheck&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;test&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sh&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;curl -f http://127.0.0.1:9000/health &amp;amp;&amp;amp; curl -f http://127.0.0.1:9001/rustfs/console/health&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;interval&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;30s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;retries&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;start_period&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;40s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Veillez à changer les éléments suivants - au minimum :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;./storage_data&lt;/code&gt; dans la section &lt;em&gt;volumes&lt;/em&gt;. Renseigner par un &lt;strong&gt;dossier&lt;/strong&gt; dans lequel vous voulez &lt;strong&gt;stocker les données&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RUSTFS_ACCESS_KEY&lt;/code&gt; dans la section &lt;em&gt;environment&lt;/em&gt;. Changez &lt;em&gt;olivier&lt;/em&gt; par un &lt;strong&gt;identifiant&lt;/strong&gt; que vous souhaitez utiliser,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RUSTFS_SECRET_KEY&lt;/code&gt; dans la section &lt;em&gt;environment&lt;/em&gt;. Changez la valeur &lt;em&gt;mot2passe&lt;/em&gt; par quelque chose de bien plus long et bien plus compliqué que cela (une &lt;strong&gt;clé secrète&lt;/strong&gt; en somme).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;De cette façon, le service va se lancer avec des ports choisis par Docker Compose. Vous pouvez les connaître en tapant les commandes suivantes :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker compose port rustfs &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker compose port rustfs &lt;span style=&#34;color:#ae81ff&#34;&gt;9001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On constate sur l&amp;rsquo;interface (port initial 9001), après s&amp;rsquo;être authentifié avec l&amp;rsquo;identifiant et la clé secrète, qu&amp;rsquo;il n&amp;rsquo;y aucun bucket.&lt;/p&gt;
&lt;h2 id=&#34;initialisation-des-buckets&#34;&gt;Initialisation des buckets&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Qu&amp;rsquo;est un bucket ?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C&amp;rsquo;est un &lt;strong&gt;espace qui regroupe plusieurs objets&lt;/strong&gt; qu&amp;rsquo;on aurait déposé à cet endroit. Cela permet de se repérer plus facilement dans un espace de stockage objet.&lt;/p&gt;
&lt;p&gt;Afin de créer un bucket, soit on utilise l&amp;rsquo;interface (méthode manuelle), soit on créé un conteneur d&amp;rsquo;initialisation qui fera le job à notre place (automatique).&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;opte pour le &lt;strong&gt;conteneur d&amp;rsquo;initialisation&lt;/strong&gt; pour créer 3 buckets. Dans notre fichier docker-compose.yaml on ajoute les lignes suivantes :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;init_buckets&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;minio/mc:RELEASE.2025-08-13T08-35-41Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;depends_on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;rustfs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;on&lt;/span&gt;-&lt;span style=&#34;color:#ae81ff&#34;&gt;failure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;entrypoint&lt;/span&gt;: &amp;gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /bin/sh -c &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      sleep 5;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /usr/bin/mc alias set s3server http://rustfs:9000 \&amp;#34;olivier\&amp;#34; \&amp;#34;mot2passe\&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /usr/bin/mc mb s3server/default;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /usr/bin/mc mb s3server/bucket1;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /usr/bin/mc mb s3server/bucket2;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      exit 0;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Pensez à changer olivier et mot2passe&lt;/strong&gt; par les mêmes identifiants/mot de passe que renseignés dans le service &lt;code&gt;rustfs&lt;/code&gt; du docker-compose.yaml précédent.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;astuce est donc d&amp;rsquo;utiliser le client &lt;code&gt;mc&lt;/code&gt; de MinIO pour ajouter les buckets qu&amp;rsquo;on souhaiterait. Dans l&amp;rsquo;exemple présenté ci-avant, le conteneur d&amp;rsquo;initialisation permet de créer 3 buckets :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;default&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;&lt;em&gt;bucket1&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;&lt;em&gt;bucket2&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Libre à vous d&amp;rsquo;adapter ce conteneur pour répondre à vos besoins en matière de création initiale de bucket.&lt;/p&gt;
&lt;p&gt;Il ne reste alors plus que la mise à disposition sur Internet via l&amp;rsquo;usage de sous-domaines et de Træfik.&lt;/p&gt;
&lt;h2 id=&#34;configurer-les-labels-pour-træfik&#34;&gt;Configurer les labels pour Træfik&lt;/h2&gt;
&lt;p&gt;Træfik est un proxy souvent utilisé avec Docker Compose pour se charger des routes. L&amp;rsquo;idée de Træfik est d&amp;rsquo;&lt;strong&gt;utiliser le champ &lt;code&gt;labels&lt;/code&gt;&lt;/strong&gt; pour récupérer des instructions utiles à la &lt;strong&gt;création des routes en lien avec les domaines&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Pour RustFS sous Docker Compose, et avec Træfik en frontal, je suggère les labels suivants :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.enable=true&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.api-rustfs.rule=Host(`api.mondomaine.tld`)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.api-rustfs.entrypoints=websecure&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.api-rustfs.service=api-rustfs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.api-rustfs.loadbalancer.server.port=9000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.rustfs.rule=Host(`mondomaine.tld`)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.rustfs.entrypoints=websecure&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.rustfs.service=rustfs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.rustfs.loadbalancer.server.port=9001&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Prenez soin de changer les éléments suivants&lt;/strong&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;websecure&lt;/code&gt; par le &lt;strong&gt;nom de votre routeur&lt;/strong&gt; permettant d&amp;rsquo;avoir du HTTPS,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;api.mondomaine.tld&lt;/code&gt; par le &lt;strong&gt;domaine de votre choix&lt;/strong&gt; pour accéder à l&amp;rsquo;API de RustFS,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mondomaine.tld&lt;/code&gt; par le &lt;strong&gt;domaine utilisé&lt;/strong&gt; pour accéder à l&amp;rsquo;&lt;strong&gt;interface Web&lt;/strong&gt; de RustFS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Évidemment tout un tas d&amp;rsquo;autres options sont possibles, il suffit de lire la documentation de Træfik pour cela.&lt;/p&gt;
&lt;h2 id=&#34;résultat-final-complet&#34;&gt;Résultat final complet&lt;/h2&gt;
&lt;p&gt;Ce qui nous donne :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;rustfs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rustfs/rustfs:1.0.0-alpha.82&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;9001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;./storage_data:/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;/etc/timezone:/etc/timezone:ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_VOLUMES=/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_ADDRESS=0.0.0.0:9000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_CONSOLE_ADDRESS=0.0.0.0:9001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_CONSOLE_ENABLE=true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_ACCESS_KEY=olivier&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_SECRET_KEY=mot2passe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;RUSTFS_OBS_LOGGER_LEVEL=info&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;healthcheck&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;test&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sh&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;curl -f http://127.0.0.1:9000/health &amp;amp;&amp;amp; curl -f http://127.0.0.1:9001/rustfs/console/health&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;interval&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;30s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;retries&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;start_period&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;40s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.enable=true&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.api-rustfs.rule=Host(`api.mondomaine.tld`)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.api-rustfs.entrypoints=websecure&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.api-rustfs.service=api-rustfs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.api-rustfs.loadbalancer.server.port=9000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.rustfs.rule=Host(`mondomaine.tld`)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.rustfs.entrypoints=websecure&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.rustfs.service=rustfs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.rustfs.loadbalancer.server.port=9001&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;init_buckets&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;minio/mc:RELEASE.2025-08-13T08-35-41Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;depends_on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;rustfs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;on&lt;/span&gt;-&lt;span style=&#34;color:#ae81ff&#34;&gt;failure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;entrypoint&lt;/span&gt;: &amp;gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /bin/sh -c &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      sleep 5;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /usr/bin/mc alias set s3server http://rustfs:9000 \&amp;#34;olivier\&amp;#34; \&amp;#34;mot2passe\&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /usr/bin/mc mb s3server/default;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /usr/bin/mc mb s3server/bucket1;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      /usr/bin/mc mb s3server/bucket2;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      exit 0;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Avec ce contenu vous devriez pouvoir &lt;strong&gt;démarrer une instance RustFS&lt;/strong&gt; sans problème &amp;#x1f609;.&lt;/p&gt;
&lt;h1 id=&#34;quelle-aventure&#34;&gt;Quelle aventure !&lt;/h1&gt;
&lt;p&gt;Au bout du compte, avoir cherché à lancer un service de stockage objet a été une &lt;strong&gt;sacrée odyssée pour moi&lt;/strong&gt;. Beaucoup d&amp;rsquo;aléas liés au &lt;strong&gt;changement de politique de Bitnami&lt;/strong&gt; (pour les images MinIO), à l&amp;rsquo;&lt;strong&gt;arrêt de maintenance du code du serveur MinIO&lt;/strong&gt; par AIStor et aux &lt;strong&gt;effets de bord de RustFS&lt;/strong&gt; en plein développement.&lt;/p&gt;
&lt;p&gt;Mes besoins spécifiques en terme d&amp;rsquo;infrastructure (Docker Compose et Træfik) m&amp;rsquo;ont amené à devoir retravailler plusieurs fois le fichier docker-compose.yaml. Et j&amp;rsquo;ai essuyé quelques plâtres avant d&amp;rsquo;avoir une instance fonctionnelle.&lt;/p&gt;
&lt;p&gt;Je suis ainsi &lt;strong&gt;content de partager ce fichier docker-compose.yaml&lt;/strong&gt;. Bien qu&amp;rsquo;il y a matière à faire évoluer ce fichier. On peut imaginer &lt;strong&gt;améliorer ce fichier&lt;/strong&gt; en utilisant des &lt;strong&gt;variables&lt;/strong&gt; pour le dossier où seront stockées les données, le nom du service, le domaine et bien évidemment l&amp;rsquo;identifiant et le mot de passe du service RustFS. Et déposer les valeurs dans &lt;strong&gt;un fichier .env&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;On pourrait également trouver un autre client que &lt;code&gt;mc&lt;/code&gt; pour &lt;strong&gt;initialiser les buckets&lt;/strong&gt; au départ. Voire trouver un autre outil permettant de créer les buckets plus facilement. Imaginons une nouvelle image Docker ayant un script d&amp;rsquo;initialisation avec des variables d&amp;rsquo;environnement le permettant.&lt;/p&gt;
&lt;p&gt;Je laisse votre imagination faire le reste &amp;#x1f60a;.&lt;/p&gt;
&lt;h1 id=&#34;sources-utilisées-pour-la-mise-en-place-de-rustfs&#34;&gt;Sources utilisées pour la mise en place de RustFS&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rustfs/rustfs/issues/555&#34;&gt;Benchmarks de plusieurs solutions alternatives à Minio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.rustfs.com/concepts/comparison.html&#34;&gt;Comparaison à Ceph et MinIO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.rustfs.com/management/bucket/creation.html&#34;&gt;Documentation sur la création de buckets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rustfs/rustfs/blob/main/docker-compose.yml&#34;&gt;Fichier docker-compose.yml d&amp;rsquo;exemple sur le dépôt Github du projet RustFS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.rustfs.com/developer/mc.html&#34;&gt;Documentation sur l&amp;rsquo;utilisation du client MinIO Client (mc) pour RustFS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://belginux.com/installer-rustfs-avec-docker/&#34;&gt;Tutoriel d&amp;rsquo;installation de RustFS avec Docker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;liens-utiles&#34;&gt;Liens utiles&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rustfs/rustfs/issues/1838&#34;&gt;Bug RustFS (ticket Github) version 1.0.0-alpha.83 sur l&amp;rsquo;architecture de ma machine&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/bitnami/charts/issues/35164&#34;&gt;Décision drastique prise par Bitnami&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rustfs/rustfs&#34;&gt;Dépôt Github de RustFS&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/pgsty/minio&#34;&gt;Fork de MinIO&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hub.docker.com/r/rustfs/rustfs&#34;&gt;Images docker officielles de RustFS sur le Hub Docker&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://fr.wikipedia.org/wiki/Stockage_objet&#34;&gt;Le stockage objet selon Wikipédia&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://fr.wikipedia.org/wiki/Amazon_S3&#34;&gt;S3 selon Wikipédia&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://velero.io/docs/&#34;&gt;Velero (documentation)&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://velero.io/&#34;&gt;Velero&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
	    <title>Mon Labo K8S pour essayer des applications</title>
      <link>https://olivier.dossmann.net/2025/11/mon-labo-k8s-pour-essayer-des-applications/</link>
      <pubDate>Sun, 09 Nov 2025 06:25:39 +0100</pubDate>
      
      <guid>https://olivier.dossmann.net/2025/11/mon-labo-k8s-pour-essayer-des-applications/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Quand on commence à étudier Kubernetes (k8s), on a &lt;strong&gt;besoin d&amp;rsquo;un environnement où tester&lt;/strong&gt; ce qu&amp;rsquo;on apprend. Les environnements possibles sont nombreux : &lt;a href=&#34;https://minikube.sigs.k8s.io/docs/&#34;&gt;Minikube&lt;/a&gt;, &lt;a href=&#34;https://kubernetes.io/fr/&#34;&gt;Kubernetes (k8s) officiel&lt;/a&gt;, &lt;a href=&#34;https://k0sproject.io/&#34;&gt;k0s&lt;/a&gt;, &lt;a href=&#34;https://k3s.io/&#34;&gt;k3s&lt;/a&gt;, etc. Cela ne s&amp;rsquo;arrête plus !&lt;/p&gt;
&lt;p&gt;Entre les &lt;strong&gt;difficultés à installer l&amp;rsquo;environnement&lt;/strong&gt; et celles à appliquer ce qu&amp;rsquo;on apprend, on ne s&amp;rsquo;en sort plus. Cela devient &lt;strong&gt;vite compliqué&lt;/strong&gt; au point de vouloir tout arrêter ; c&amp;rsquo;était mon cas.&lt;/p&gt;
&lt;p&gt;De plus je souhaitais avoir un environnement reproductible et spécifique à chacun de mes projets, de quoi travailler unitairement sur un service particulier.&lt;/p&gt;
&lt;p&gt;Avant de décrocher complètement, j&amp;rsquo;ai fait une pause, &lt;strong&gt;pris du recul&lt;/strong&gt; et étudié la question. Je vous relate ici le résultat de cette petite aventure dans le monde de Kubernetes et des outils envisagés pour &lt;strong&gt;créer un labo de développement&lt;/strong&gt; d&amp;rsquo;applications tournant sous Kubernetes.&lt;/p&gt;
&lt;p&gt;Dans un premier temps nous poserons le problème, après quoi nous étudierons quelques solutions pour finalement détailler le produit de cette pérégrination.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/objets/tubes_a_essai.jpg&#34; alt=&#34;Quelques tubes à essais avec une pipette vus de près&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur &lt;a href=&#34;https://www.publicdomainpictures.net/fr/view-image.php?image=45299&amp;amp;picture=tubes-a-essai&#34;&gt;publicdomainpictures.net&lt;/a&gt;&lt;/em&gt; sous Licence CC0 Public Domain.&lt;/p&gt;
&lt;h1 id=&#34;le-contexte&#34;&gt;Le contexte&lt;/h1&gt;
&lt;p&gt;Venant du &lt;a href=&#34;https://olivier.dossmann.net/tags/docker/&#34;&gt;monde de Docker et Docker Compose&lt;/a&gt;, il me semblait aller de soi d&amp;rsquo;étudier ensuite le monde de Kubernetes - qui utilise la conteneurisation. Seulement je ne pensais pas que l&amp;rsquo;installation même de &lt;strong&gt;Kubernetes était un cap à franchir&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Je souhaite en &lt;strong&gt;profiter pour migrer&lt;/strong&gt; petit à petit &lt;strong&gt;mes services sur Kubernetes&lt;/strong&gt;. Chacun d&amp;rsquo;eux devient donc un projet en soi. Et comme souvent, &lt;strong&gt;j&amp;rsquo;aime avoir un environnement spécifique de développement&lt;/strong&gt; pour créer les fichiers nécessaires à Kubernetes et permettre a posteriori d&amp;rsquo;améliorer le service. Je cherche donc à avoir un simili de docker-compose.yml pour chaque service et permettant de développer l&amp;rsquo;application dans un environnement Kubernetes propre.&lt;/p&gt;
&lt;p&gt;Au début on découvre &lt;a href=&#34;https://minikube.sigs.k8s.io/docs/&#34;&gt;&lt;strong&gt;Minikube&lt;/strong&gt;&lt;/a&gt;. Du moins c&amp;rsquo;est un outil très souvent conseillé. &lt;strong&gt;Pratique&lt;/strong&gt; sur une machine bureautique pour triturer rapidement quelques fichiers Kubernetes (des fichiers au format YAML). Il est &lt;strong&gt;bien documenté&lt;/strong&gt; et possède plusieurs plugins pour faciliter l&amp;rsquo;étude du Kubernetes en place ; par exemple un &lt;strong&gt;plugin Dashboard&lt;/strong&gt; permet de visualiser les métriques du serveur et les objets instanciés. J&amp;rsquo;ai la sensation que cet outil reste « trop spécifique ». Il ne représente pas totalement un « vrai » Kubernetes. Ça peut parfois causer des torts au moment de déployer sur un autre serveur Kubernetes. L&amp;rsquo;outil est également &lt;strong&gt;lourd&lt;/strong&gt; et relativement &lt;strong&gt;lent&lt;/strong&gt; pour instancier un nouvel environnement.&lt;/p&gt;
&lt;p&gt;Pourquoi ne pas tester un Kubernetes connu pour sa légèreté ? Par exemple &lt;a href=&#34;https://k3s.io/&#34;&gt;&lt;strong&gt;k3s&lt;/strong&gt;&lt;/a&gt;. D&amp;rsquo;autant qu&amp;rsquo;il s&amp;rsquo;installe rapidement à l&amp;rsquo;aide de &lt;a href=&#34;https://github.com/alexellis/k3sup&#34;&gt;&lt;strong&gt;k3sup&lt;/strong&gt;&lt;/a&gt; (qui fonctionne à merveille). Sur le papier c&amp;rsquo;est une bonne idée : &lt;strong&gt;léger, facile à installer&lt;/strong&gt;. En revanche il &lt;strong&gt;ne permet pas d&amp;rsquo;instancier un nouvel environnement&lt;/strong&gt; ; il faut donc jouer avec les namespaces Kubernetes. Rebelote : ce n&amp;rsquo;est pas un outil adapté à l&amp;rsquo;apprentissage de Kubernetes. Au départ on fait forcément des erreurs dues à l&amp;rsquo;incompréhension ou l&amp;rsquo;ignorance ; ce qui peut rendre l&amp;rsquo;environnement rapidement inutilisable.&lt;/p&gt;
&lt;p&gt;Après ces deux premières tentatives, je sais désormais ce que je veux :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;possibilité de &lt;strong&gt;créer un environnement « propre »&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;encore mieux s&amp;rsquo;il peut créer &lt;strong&gt;plusieurs environnements&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;si possible &lt;strong&gt;léger&lt;/strong&gt; (petit) - ce qui exclue les machines virtuelles,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;facile à installer&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;et &lt;strong&gt;rapide&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nous avons nos critères, il ne reste plus qu&amp;rsquo;à chercher le(s) outil(s) permettant de créer rapidement un environnement de développement autour de Kubernetes.&lt;/p&gt;
&lt;h1 id=&#34;solutions-étudiées&#34;&gt;Solutions étudiées&lt;/h1&gt;
&lt;p&gt;À la recherche des mots clés « lightweight » (similaire au mot léger) et « kubernetes » dans un moteur de recherche, on trouve plusieurs outils comme :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://microk8s.io/&#34;&gt;MicroK8S&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://k0sproject.io/&#34;&gt;k0s&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://k3s.io/&#34;&gt;k3s&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;et &lt;a href=&#34;https://kind.sigs.k8s.io/&#34;&gt;kind&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;k3s&lt;/strong&gt; a déjà été cité dans cet article. Il ne me convient pas pour un environnement de développement/d&amp;rsquo;étude concernant k8s. Il est sûrement très &lt;strong&gt;redoutable à l&amp;rsquo;installation rapide&lt;/strong&gt; sur une quantité importante de machines à l&amp;rsquo;aide de &lt;a href=&#34;https://github.com/alexellis/k3sup&#34;&gt;k3sup&lt;/a&gt;. Mais ce n&amp;rsquo;est pas le sujet de cet article.&lt;/p&gt;
&lt;p&gt;La liste mentionne également &lt;a href=&#34;https://microk8s.io/&#34;&gt;&lt;strong&gt;MicroK8S&lt;/strong&gt;&lt;/a&gt;, le petit rejeton de la famille Ubuntu, qui semble être une &lt;strong&gt;alternative à &lt;a href=&#34;https://minikube.sigs.k8s.io/docs/&#34;&gt;Minikube&lt;/a&gt;&lt;/strong&gt; avec des &lt;strong&gt;plugins&lt;/strong&gt; (Dashboard, DNS, registry, istio, etc.). Je pense qu&amp;rsquo;il est effectivement intéressant pour un usage complet entre des développeurs, une intégration continue (CI) / déploiement continue (CD) et plusieurs environnements allant jusqu&amp;rsquo;à des environnements dit « de production ». Je sens cependant que la similitude avec Minikube ne puisse me convenir. Je le &lt;strong&gt;laisse de côté pour l&amp;rsquo;instant&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://k0sproject.io/&#34;&gt;&lt;strong&gt;k0s&lt;/strong&gt;&lt;/a&gt;, quant à lui, semble être la &lt;strong&gt;solution idéale pour&lt;/strong&gt; une installation sur &lt;strong&gt;une machine physique&lt;/strong&gt;. À &lt;strong&gt;usage privé&lt;/strong&gt;. Bien qu&amp;rsquo;il semble &lt;strong&gt;léger, facile à installer&lt;/strong&gt; et utiliser, je comprends rapidement qu&amp;rsquo;il est fait pour avoir une installation unique sur une machine physique précise. Il &lt;strong&gt;ne répond pas à&lt;/strong&gt; mon critère de &lt;strong&gt;création multiple d&amp;rsquo;environnements&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Et un de plus en moins !&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Il reste le dernier de cette liste : &lt;a href=&#34;https://kind.sigs.k8s.io/&#34;&gt;&lt;strong&gt;kind&lt;/strong&gt;&lt;/a&gt;. A priori il semble &lt;strong&gt;léger&lt;/strong&gt;, prévu pour un usage &lt;strong&gt;spécifique au développement&lt;/strong&gt; ou de l&amp;rsquo;&lt;strong&gt;intégration continue&lt;/strong&gt; (CI) et &lt;strong&gt;utilise Docker&lt;/strong&gt; pour créer un cluster complet à chaque fois. Waouh, rien que ça ! Sur le papier, cet outil est &lt;strong&gt;très prometteur&lt;/strong&gt; car il répond aux critères précédemment listés :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;créer des environnements « propres » grâce à l&amp;rsquo;usage de Docker,&lt;/li&gt;
&lt;li&gt;ainsi il permet l&amp;rsquo;usage de plusieurs environnements,&lt;/li&gt;
&lt;li&gt;il est léger, petit,&lt;/li&gt;
&lt;li&gt;facile à installer puisque &lt;a href=&#34;https://aur.archlinux.org/packages/kind&#34;&gt;kind est disponible dans les dépôts AUR d&amp;rsquo;ArchLinux&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;et pour la rapidité nous verrons.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;À l&amp;rsquo;usage, kind (qui veut dire Kubernetes IN Docker) semble &lt;strong&gt;facile à prendre en main&lt;/strong&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Créer un cluster nommé olivier&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kind create cluster --name olivier
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Supprime le cluster nommé olivier&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kind delete cluster --name olivier
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Une fois le cluster créé, il s&amp;rsquo;agit simplement de jouer avec la commande &lt;code&gt;kubectl&lt;/code&gt; habituelle pour contacter le cluster. Et la commande étant à taper, je peux tout à fait &lt;strong&gt;scripter la création du cluster&lt;/strong&gt; et sa destruction.&lt;/p&gt;
&lt;p&gt;Il serait plus pratique de l&amp;rsquo;utiliser avec &lt;strong&gt;d&amp;rsquo;autres outils pour en faciliter l&amp;rsquo;usage&lt;/strong&gt;. J&amp;rsquo;ai donc cherché au fur et à mesure de nouveaux outils dont voici la liste :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ahmetb/kubectx&#34;&gt;&lt;strong&gt;kubectx&lt;/strong&gt;&lt;/a&gt; va permettre de &lt;strong&gt;commuter&lt;/strong&gt; d&amp;rsquo;&lt;strong&gt;un contexte Kubernetes&lt;/strong&gt; à un autre. Autrement dit passer d&amp;rsquo;un cluster à un autre facilement,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/yannh/kubeconform&#34;&gt;&lt;strong&gt;kubeconform&lt;/strong&gt;&lt;/a&gt; pour &lt;strong&gt;valider&lt;/strong&gt; nos fichiers YAML,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/stackrox/kube-linter&#34;&gt;&lt;strong&gt;kube-linter&lt;/strong&gt;&lt;/a&gt; pour pousser à l&amp;rsquo;usage des &lt;strong&gt;bonnes pratiques&lt;/strong&gt; en matière de rédaction de fichiers YAML,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://skaffold.dev/&#34;&gt;&lt;strong&gt;skaffold&lt;/strong&gt;&lt;/a&gt; pour &lt;strong&gt;surveiller&lt;/strong&gt; la moindre modification (équivalent d&amp;rsquo;un « watcher ») sur nos fichiers YAML et les déployer directement sur le cluster,&lt;/li&gt;
&lt;li&gt;et &lt;a href=&#34;https://fr.wikipedia.org/wiki/Make&#34;&gt;&lt;strong&gt;make&lt;/strong&gt;&lt;/a&gt; (avec un &lt;strong&gt;fichier Makefile&lt;/strong&gt;) pour mélanger tout ça.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mon idée est d&amp;rsquo;utiliser un fichier Makefile pour fournir plusieurs commandes permettant de créer le cluster, le détruire, vérifier les fichiers YAML ou encore lancer un déploiement automatique s&amp;rsquo;il y a des changements dans les fichiers en cours de développement.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;imagine quelque chose comme :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make cluster&lt;/code&gt; pour &lt;strong&gt;créer un cluster&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make dev&lt;/code&gt; pour lancer skaffold et &lt;strong&gt;écouter le moindre changement&lt;/strong&gt; sur le dossier de développement de l&amp;rsquo;application,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make kubeconform&lt;/code&gt; pour &lt;strong&gt;vérifier&lt;/strong&gt; les fichiers une fois écrits,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make lint&lt;/code&gt; pour vérifier les &lt;strong&gt;bonnes pratiques&lt;/strong&gt; avec kube-linter,&lt;/li&gt;
&lt;li&gt;et &lt;code&gt;make clean&lt;/code&gt; pour &lt;strong&gt;détruire le cluster&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tentons l&amp;rsquo;aventure et voyons le résultat !&lt;/p&gt;
&lt;h1 id=&#34;ce-que-jai-finalement-produit&#34;&gt;Ce que j&amp;rsquo;ai finalement produit&lt;/h1&gt;
&lt;h2 id=&#34;en-bref&#34;&gt;En bref&lt;/h2&gt;
&lt;p&gt;Le fichier &lt;strong&gt;Makefile&lt;/strong&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Makefile&#34; data-lang=&#34;Makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CLUSTER_NAME &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; k8s-dev-example
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;KUBECTL &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; kubectl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SKAFFOLD &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; skaffold
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;KIND &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; kind
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;KUBECONFORM &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; kubeconform
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;KUSTOMIZE &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; kustomize
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NAMESPACES &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;.PHONY&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; help
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;help&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	@echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Commandes disponibles :&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	@echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  make cluster       - Crée un cluster Kind&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	@echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  make namespaces    - Crée les namespaces Kubernetes (dev/staging/prod)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	@echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  make dev           - Lance Skaffold pour l&amp;#39;env dev&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	@echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  make kubeconform   - Lance kubeconform sur l&amp;#39;env de DEV&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	@echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  make clean         - Supprime le cluster Kind&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;cluster&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;KIND&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt; create cluster --name &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;CLUSTER_NAME&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;namespaces&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	@for ns in &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;NAMESPACES&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;KUBECTL&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt; get ns $$ns &amp;gt;/dev/null 2&amp;gt;&amp;amp;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;KUBECTL&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt; create ns $$ns; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;dev&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; cluster namespaces
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;SKAFFOLD&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt; dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;kubeconform&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; kubeconform-dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;kubeconform-dev&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;KUSTOMIZE&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt; build overlays/dev | &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;KUBECONFORM&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt; -strict -summary -ignore-missing-schemas
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;clean&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;KIND&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt; delete cluster --name &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;CLUSTER_NAME&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ce &lt;a href=&#34;https://gitlab.com/odtre/templates/k8s-dev-example/&#34;&gt;fichier Makefile est disponible sur le dépôt Gitlab d&amp;rsquo;ODTRE&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Il va utiliser deux dossiers principaux :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;base&lt;/strong&gt; qui contient les fichiers YAML de l&amp;rsquo;application qu&amp;rsquo;on souhaite implémenter sur Kubernetes,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;overlays/dev&lt;/strong&gt; qui contient un fichier kustomization.yaml pour surcharger le dossier &lt;em&gt;base&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et 2 fichiers de configuration :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;kube-linter.yaml&lt;/strong&gt; avec votre configuration de l&amp;rsquo;outil,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;skaffold.yaml&lt;/strong&gt; avec le contenu suivant :&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;skaffold/v4beta13&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;k8s-demo-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;manifests&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;kustomize&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;paths&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;./overlays/dev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Exemple de redirection de port sur le service nommé dev-nginx (car l&amp;#39;overlay ajoute dev- devant tout)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;portForward&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;resourceType&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;resourceName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;dev-nginx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;dev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;localPort&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;4000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cela permet de surveiller le dossier &lt;em&gt;./overlays/dev&lt;/em&gt; avec &lt;em&gt;kustomize&lt;/em&gt; pour interpréter les fichiers. Et il va ouvrir le &lt;strong&gt;port 4000&lt;/strong&gt; sur la machine locale pour &lt;strong&gt;rediriger sur le port 80&lt;/strong&gt; du service Nginx d&amp;rsquo;exemple (fourni dans le dépôt Gitlab mentionné précédemment).&lt;/p&gt;
&lt;h2 id=&#34;à-lusage&#34;&gt;À l&amp;rsquo;usage&lt;/h2&gt;
&lt;p&gt;Tout n&amp;rsquo;est pas parfait. Cependant ce fichier Makefile permet de lancer quelques commandes &lt;code&gt;make&lt;/code&gt; utiles :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Lance l&amp;#39;environnement de DEV. Si le cluster n&amp;#39;existe pas : il le créé. Sinon il ignore.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Vérifie la conformité des fichiers YAML en utilisant le dossier overlays/dev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make kubeconform
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Détruit le cluster de DEV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make clean
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Pousse à l&amp;#39;usage des bonnes pratiques sur les fichiers contenus dans le dossier ./base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kube-linter lint --config kube-linter.yaml ./base
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour toute aide supplémentaire, faites : &lt;code&gt;make help&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ainsi &lt;strong&gt;il devient facile de travailler sur un nouvel environnement&lt;/strong&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;je copie les fichiers disponible sur un &lt;a href=&#34;https://gitlab.com/odtre/templates/k8s-dev-example/&#34;&gt;dépôt template sur Gitlab&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;j&amp;rsquo;ouvre le fichier Makefile en écriture,&lt;/li&gt;
&lt;li&gt;j&amp;rsquo;édite la ligne suivante pour adapter le nom du cluster de travail :&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CLUSTER_NAME :&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; k8s-dev-example
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et le tour est joué !&lt;/p&gt;
&lt;p&gt;Je suis assez &lt;strong&gt;satisfait de cet environnement&lt;/strong&gt;. Il &lt;strong&gt;répond aux critères&lt;/strong&gt; édictés plusieurs fois dans cet article. Et je me sens plus à l&amp;rsquo;aise de pouvoir modifier comme bon me semble cet environnement de développement/travail.&lt;/p&gt;
&lt;p&gt;Les outils utilisés me font penser à &lt;strong&gt;une boîte à outil&lt;/strong&gt; de base pour le &lt;strong&gt;travail sur Kubernetes&lt;/strong&gt;. Même sans utiliser le fichier Makefile je suis amené à pratiquer les outils comme kubeconform, kubectl, kube-linter et kustomize.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est donc une très bonne chose d&amp;rsquo;avoir regroupé ces outils autour de Makefile et de les utiliser régulièrement sur mes projets Kubernetes.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Nous avons posé le contexte d&amp;rsquo;une &lt;strong&gt;recherche d&amp;rsquo;outil&lt;/strong&gt; simple, rapide et léger &lt;strong&gt;pour créer de nombreux environnements Kubernetes&lt;/strong&gt; afin de travailler sur ces environnements dans le cadre d&amp;rsquo;un &lt;strong&gt;développement de fichiers YAML&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Après quelques essais sur Minikube et k3s, mes recherches se sont portées sur l&amp;rsquo;&lt;strong&gt;utilisation de kind&lt;/strong&gt;. Puis j&amp;rsquo;ai utilisé make pour le manipuler et regrouper aussi les différents outils utiles.&lt;/p&gt;
&lt;p&gt;La &lt;strong&gt;boîte à outil&lt;/strong&gt; se compose de :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;kind&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;skaffold&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kubectl&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kubeconform&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kube-linter&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;et &lt;strong&gt;make&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;aborde désormais de &lt;strong&gt;manière plus sereine&lt;/strong&gt; le développement d&amp;rsquo;une application qui sera hébergée par un Kubernetes. J&amp;rsquo;ai un template à ma disposition pour ces fichiers. Template que je peux faire évoluer au gré des obstacles rencontrés. Il utilise tous les outils que j&amp;rsquo;ai appréciés. J&amp;rsquo;en suis &lt;strong&gt;pleinement satisfait&lt;/strong&gt; &amp;#x1f60e; .&lt;/p&gt;
&lt;p&gt;Et vous, &lt;strong&gt;quel environnement Kubernetes utilisez-vous&lt;/strong&gt; pour vos développements de fichiers YAML ?&lt;/p&gt;
&lt;h1 id=&#34;liens-utiles&#34;&gt;Liens utiles&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://kubernetes.io/fr/&#34;&gt;Kubernetes (k8s) officiel&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://microk8s.io/&#34;&gt;MicroK8S&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://minikube.sigs.k8s.io/docs/&#34;&gt;Minikube&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://k0sproject.io/&#34;&gt;k0s&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://k3s.io/&#34;&gt;k3s&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://kind.sigs.k8s.io/&#34;&gt;kind&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/stackrox/kube-linter&#34;&gt;kube-linter&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/yannh/kubeconform&#34;&gt;kubeconform&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ahmetb/kubectx&#34;&gt;kubectx&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://fr.wikipedia.org/wiki/Make&#34;&gt;make&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://skaffold.dev/&#34;&gt;skaffold&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/odtre/templates/k8s-dev-example/&#34;&gt;dépôt Gitlab du template proposé dans cet article pour développer sur un environnement Kubernetes « propre »&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
	    <title>Ce que j&#39;aurais voulu savoir sur Gitlab CI</title>
      <link>https://olivier.dossmann.net/2025/05/ce-que-jaurais-voulu-savoir-sur-gitlab-ci/</link>
      <pubDate>Sun, 18 May 2025 13:55:39 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2025/05/ce-que-jaurais-voulu-savoir-sur-gitlab-ci/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Il y a quelques mois &lt;a href=&#34;https://olivier.dossmann.net/2024/10/mes_conseils_pour_reussir_une_formation_bootcamp/&#34;&gt;je parlais de ma formation Bootcamp pour devenir Ingénieur DevOps&lt;/a&gt;. J&amp;rsquo;y ai utilisé - à nouveau - &lt;strong&gt;Gitlab CI&lt;/strong&gt; (Continuous Integration). Vous savez, cet &lt;strong&gt;outil permettant d&amp;rsquo;exécuter des actions&lt;/strong&gt; après avoir envoyé votre code/dépôt sur la plateforme Gitlab ?&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est très utile, par exemple pour &lt;strong&gt;lancer les tests&lt;/strong&gt; sur votre code, vérifier que &lt;strong&gt;le code s&amp;rsquo;exécute dans un environnement précis&lt;/strong&gt; ou tout simplement vérifier que &lt;strong&gt;le code compile&lt;/strong&gt;. Et si votre dépôt n&amp;rsquo;est pas du code, par exemple un site web, vous pouvez tester les liens morts ; voire publier votre site ! &lt;strong&gt;Les possibilités sont - finalement - nombreuses&lt;/strong&gt; !&lt;/p&gt;
&lt;p&gt;En revanche, un tel outil est parfois déstabilisant. Et des cheveux, j&amp;rsquo;en ai arrachés ! J&amp;rsquo;aurais apprécié tomber sur un article explicatif. Avec des astuces. Peut-être que le présent article m&amp;rsquo;aurait convenu, qui sait !&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;aurai par exemple aimé savoir comment &lt;strong&gt;publier facilement un site web&lt;/strong&gt;, &lt;strong&gt;tester localement&lt;/strong&gt; le fichier &lt;em&gt;.gitlab-ci.yml&lt;/em&gt; avant de l&amp;rsquo;envoyer sur Gitlab, connaître &lt;strong&gt;plus d&amp;rsquo;astuces&lt;/strong&gt; pour les mots clés Gitlab, savoir &lt;strong&gt;utiliser Docker dans Gitlab CI&lt;/strong&gt; et ce que sont les &lt;strong&gt;composants réutilisables&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Ce sont ainsi tous les sujets que nous allons aborder aujourd&amp;rsquo;hui.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/nature/raton_laveur.jpg&#34; alt=&#34;Un visage de Raton Laveur&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://www.flickr.com/photos/131830853@N05/&#34;&gt;profil de didier.camus sur Flickr&lt;/a&gt;&lt;/em&gt; sous Licence Œuvre du domaine public.&lt;/p&gt;
&lt;h1 id=&#34;publier-rapidement-un-site-statique&#34;&gt;Publier rapidement un site statique&lt;/h1&gt;
&lt;p&gt;Gitlab met à disposition des utilisateurs un &lt;strong&gt;espace permettant d&amp;rsquo;héberger des sites webs statiques&lt;/strong&gt;. Incroyable n&amp;rsquo;est-ce pas ? Cet espace est &lt;a href=&#34;https://docs.gitlab.com/user/project/pages/&#34; title=&#34;Voir la documentation de Gitlab concernant Gitlab Pages&#34;&gt;Gitlab Pages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Comment cela fonctionne ? Il suffit de créer un dépôt Gitlab, d&amp;rsquo;ajouter un fichier &lt;strong&gt;.gitlab-ci.yml&lt;/strong&gt; contenant la section suivante :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;busybox&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;pages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;The site will be deployed to $CI_PAGES_URL&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;artifacts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;paths&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;public&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;rules&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;if&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Code récupéré du projet &lt;a href=&#34;https://gitlab.com/pages/plain-html&#34;&gt;https://gitlab.com/pages/plain-html&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cela signifie qu&amp;rsquo;au terme de la CI/CD (dans l&amp;rsquo;étape nommée &lt;em&gt;deploy&lt;/em&gt;), &lt;strong&gt;le contenu du dossier public sera publié sur Gitlab Pages&lt;/strong&gt;. À quelle adresse ? Imaginons que vous partez d&amp;rsquo;un dépôt dont l&amp;rsquo;adresse est : &lt;code&gt;https://gitlab.com/blankoworld/monprojet/&lt;/code&gt;, l&amp;rsquo;adresse URL d&amp;rsquo;accès à votre site publié sera : &lt;code&gt;https://blankoworld.gitlab.io/monprojet/&lt;/code&gt;. Pratique non ?&lt;/p&gt;
&lt;p&gt;Astuce : Si votre dépôt est privé, vous pouvez quand même rendre votre site public. Il suffit d&amp;rsquo;aller dans &lt;strong&gt;Settings &amp;gt; General&lt;/strong&gt;, Section « &lt;strong&gt;Visibility, project features, permissions&lt;/strong&gt; » et dans le sous-titre « &lt;strong&gt;Pages&lt;/strong&gt; », activez la fonctionnalité. Et dans le menu déroulant à côté, choisissez « &lt;strong&gt;Everyone&lt;/strong&gt; ». N&amp;rsquo;oubliez pas de &lt;strong&gt;sauvegarder&lt;/strong&gt; cette configuration. Le code sera privé, le site web statique public !&lt;/p&gt;
&lt;p&gt;Pour &lt;strong&gt;plus d&amp;rsquo;exemple&lt;/strong&gt;, veuillez vous rendre sur la page Gitlab présentant la &lt;a href=&#34;https://gitlab.com/pages&#34; title=&#34;Liste d&#39;exemple de projets utilisant Gitlab Pages&#34;&gt;liste de projets utilisant Gitlab Pages&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;tester-avant-denvoyer-sur-le-dépôt-&#34;&gt;Tester avant d&amp;rsquo;envoyer sur le dépôt ?&lt;/h1&gt;
&lt;p&gt;Le truc vraiment embêtant avec les fichiers &lt;em&gt;.gitlab-ci.yml&lt;/em&gt;, c&amp;rsquo;est qu&amp;rsquo;&lt;strong&gt;on ne peut pas les tester sur notre machine&lt;/strong&gt; (localement). Pour avancer il faut :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;modifier le fichier &lt;em&gt;.gitlab-ci.yml&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;le valider (faire un commit),&lt;/li&gt;
&lt;li&gt;l&amp;rsquo;envoyer sur Gitlab,&lt;/li&gt;
&lt;li&gt;patienter que la pipeline se lance (et parfois se termine),&lt;/li&gt;
&lt;li&gt;bénéficier du résultat ou, dans la plupart des cas, recommencer à l&amp;rsquo;étape 1…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;À une époque on pouvait utiliser une commande &lt;code&gt;gitlab-runner exec&lt;/code&gt; en local. Mais celle-ci a été supprimée : &lt;a href=&#34;https://gitlab.com/gitlab-org/gitlab-runner/-/commit/f8508c924f80b104ec7353353e6ad0edb5daae66&#34;&gt;https://gitlab.com/gitlab-org/gitlab-runner/-/commit/f8508c924f80b104ec7353353e6ad0edb5daae66&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;Suivant ce que nous faisons dans la CI/CD de Gitlab, il est possible d&amp;rsquo;utiliser un outil bien pratique nommé &lt;strong&gt;gitlab-ci-local&lt;/strong&gt; : &lt;a href=&#34;https://github.com/firecow/gitlab-ci-local&#34; title=&#34;Se rendre sur la page Github du projet gitlab-ci-local&#34;&gt;gitlab-ci-local&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vous trouverez quelques détails de &lt;a href=&#34;https://olivier.dossmann.net/wiki/developpement/gitlab-ci-local/&#34; title=&#34;Visiter le recueil d&#39;astuces d&#39;Olivier concernant l&#39;outil gitlab-ci-local&#34;&gt;gitlab-ci-local sur mon recueil d&amp;rsquo;astuces&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;généralités&#34;&gt;Généralités&lt;/h1&gt;
&lt;p&gt;Voici quelques pistes intéressantes sur le sujet Gitlab :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Une &lt;strong&gt;documentation de départ&lt;/strong&gt; est : &lt;a href=&#34;https://docs.gitlab.com/topics/build_your_application/&#34;&gt;https://docs.gitlab.com/topics/build_your_application/&lt;/a&gt;. Elle permet d&amp;rsquo;en savoir plus sur la &lt;a href=&#34;https://docs.gitlab.com/ci/yaml/&#34; title=&#34;Lire la documentation officielle de Gitlab concernant la syntaxe du fichier *gitlab-ci.yml*&#34;&gt;syntaxe de gitlab-ci.yaml&lt;/a&gt;, les &lt;a href=&#34;https://docs.gitlab.com/ci/variables/predefined_variables/&#34; title=&#34;En savoir plus sur les variables pré-définies dans la CI Gitlab&#34;&gt;variables pré-définies&lt;/a&gt; ou encore le &lt;a href=&#34;https://docs.gitlab.com/ci/pipelines/pipeline_architectures/#basic-pipelines&#34; title=&#34;Découvrir les pipelines de Gitlab CI&#34;&gt;fonctionnement d&amp;rsquo;un pipeline dans Gitlab CI&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Toujours utiles : les actions que je nomme comme « &lt;strong&gt;globales&lt;/strong&gt; ». Par exemple les mots clés &lt;code&gt;image&lt;/code&gt;, &lt;code&gt;variables&lt;/code&gt; ou &lt;code&gt;before_script&lt;/code&gt; peuvent &lt;strong&gt;être utilisés en début du fichier&lt;/strong&gt; pour définir des actions ou des valeurs qui &lt;strong&gt;seront utilisées dans toutes les étapes du pipeline&lt;/strong&gt;. Ce qui peut être un avantage, ou un inconvénient. Exemple : &lt;code&gt;image: ubuntu:latest&lt;/code&gt; va définir que toutes les étapes se lanceront dans un docker partant de l&amp;rsquo;image Ubuntu,&lt;/li&gt;
&lt;li&gt;Entrées/sorties : &lt;strong&gt;un artefact = une sortie&lt;/strong&gt;. C&amp;rsquo;est à dire des fichiers utilisables/disponibles pour les étapes suivantes (donc en &lt;strong&gt;entrée pour les autres étapes&lt;/strong&gt;) en utilisant le mot clé &lt;strong&gt;dependencies&lt;/strong&gt; (Cf. &lt;a href=&#34;https://docs.gitlab.com/ci/jobs/job_artifacts/#fetching-artifacts)&#34;&gt;https://docs.gitlab.com/ci/jobs/job_artifacts/#fetching-artifacts)&lt;/a&gt;. Sauf si &lt;code&gt;dependencies = []&lt;/code&gt; est utilisé.&lt;/li&gt;
&lt;li&gt;Utiliser des &lt;strong&gt;variables globales en début du fichier&lt;/strong&gt; (par exemple pour les numéros de versions) fait gagner du temps sur le long terme. Exemple :&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DOCKER_VERSION&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;27.3.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;UBUNTU_VERSION&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;24.04&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Concernant le &lt;strong&gt;mot clé script&lt;/strong&gt; :
&lt;ul&gt;
&lt;li&gt;si on veut écrire plusieurs lignes, utiliser la syntaxe suivante :&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;première étape des scripts&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    echo &amp;#34;première ligne&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    echo &amp;#34;seconde ligne&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    echo &amp;#34;etc.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;limiter à 10 lignes max&lt;/strong&gt;imum,&lt;/li&gt;
&lt;li&gt;si on utilise la syntaxe pour écrire plusieurs lignes, le &lt;strong&gt;debug&lt;/strong&gt; est plus &lt;strong&gt;difficile&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pour &lt;strong&gt;organiser les étapes&lt;/strong&gt;, on peut donner à chacune d&amp;rsquo;elle une &lt;strong&gt;étape pré-requise en utilisant le mot clé « &lt;a href=&#34;https://docs.gitlab.com/ci/yaml/#needs&#34; title=&#34;En savoir plus sur le mot clé needs dans la documentation de Gitlab&#34;&gt;needs&lt;/a&gt; »&lt;/strong&gt;, cela permet de chaîner les étapes dans un certain ordre. Exemple : si on veut que l&amp;rsquo;étape « deploy » se fasse après « compile », alors à la fin de l&amp;rsquo;étape « deploy » on met &lt;code&gt;needs: [compile]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;le-cas-docker&#34;&gt;Le Cas Docker&lt;/h1&gt;
&lt;h2 id=&#34;création-dune-image-docker-dans-un-conteneur-docker&#34;&gt;Création d&amp;rsquo;une image Docker… dans un conteneur Docker&lt;/h2&gt;
&lt;p&gt;Dans la situation où vous voudriez &lt;strong&gt;fabriquer des images Docker&lt;/strong&gt;, vous allez être confrontés à plusieurs problématiques :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;il faut utiliser des commandes &lt;code&gt;docker&lt;/code&gt; pour créer des images,&lt;/li&gt;
&lt;li&gt;mais la plupart des Gitlab Runner exécutent les étapes de Gitlab CI dans un Docker,&lt;/li&gt;
&lt;li&gt;donc on se retrouve à vouloir exécuter des commandes &lt;code&gt;docker&lt;/code&gt; dans un environnement Docker.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous voyez le problème ?&lt;/p&gt;
&lt;p&gt;Pour contourner cette situation il suffit d&amp;rsquo;&lt;strong&gt;utiliser &lt;a href=&#34;https://docs.gitlab.com/ci/docker/using_docker_build/#use-docker-in-docker&#34; title=&#34;Se rendre sur la documentation officielle de Gitlab CI au sujet de Docker-in-Docker&#34;&gt;Docker-in-Docker&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;En somme le début du fichier &lt;em&gt;.gitlab-ci.yml&lt;/em&gt; ressemblera à :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DOCKER_VERSION&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;27.4.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;docker:$DOCKER_VERSION&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;docker:$DOCKER_VERSION-dind&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;sidentifier&#34;&gt;S&amp;rsquo;identifier&lt;/h2&gt;
&lt;p&gt;Pour utiliser les dépôts de conteneurs de Gitlab, rien de plus simple il suffit d&amp;rsquo;écrire le code suivant dans le fichier &lt;em&gt;.gitlab-ci.yml&lt;/em&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;docker info&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;$CI_REGISTRY_PASSWORD&amp;#34; | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nul besoin de renseigner les variables. Elles sont renseignées par Gitlab CI.&lt;/p&gt;
&lt;h2 id=&#34;construire-limage&#34;&gt;Construire l&amp;rsquo;image&lt;/h2&gt;
&lt;p&gt;Pour construire l&amp;rsquo;image cela va ressembler à :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;CONTAINER_TEST_IMAGE&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;build-image&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;docker pull &amp;#34;$CONTAINER_TEST_IMAGE&amp;#34; || true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t $CONTAINER_TEST_IMAGE .&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;docker push $CONTAINER_TEST_IMAGE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On part du principe que &lt;strong&gt;le fichier Dockerfile est situé à la racine&lt;/strong&gt; de votre projet Gitlab.&lt;/p&gt;
&lt;p&gt;CONTAINER_TEST_IMAGE est une variable &lt;strong&gt;globale&lt;/strong&gt; construite à partir des &lt;a href=&#34;https://docs.gitlab.com/ci/variables/predefined_variables/&#34; title=&#34;En savoir plus sur les variables pré-définies de Gitlab CI dans la documentation officielle de Gitlab&#34;&gt;&lt;strong&gt;variables pré-définies&lt;/strong&gt; de Gitlab CI&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pousser-limage-sur-le-dépôt&#34;&gt;Pousser l&amp;rsquo;image sur le dépôt&lt;/h2&gt;
&lt;p&gt;Dans cette situation nous sommes contents d&amp;rsquo;avoir déjà ajouté l&amp;rsquo;authentification aux dépôts de conteneurs Gitlab.&lt;/p&gt;
&lt;p&gt;Cette fois on fait une étape pour récupérer l&amp;rsquo;image précédente et lui donner un nouveau nom :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;push-image&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;push&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;export IMAGE_TAG=&amp;#34;$(date +&amp;#39;%Y%m%d&amp;#39;)-${CI_COMMIT_SHORT_SHA}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;docker pull $CONTAINER_TEST_IMAGE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;docker tag $CONTAINER_TEST_IMAGE $CI_REGISTRY_IMAGE:$IMAGE_TAG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;docker push $CI_REGISTRY_IMAGE:$IMAGE_TAG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;rules&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;if&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;$CI_COMMIT_BRANCH == &amp;#34;main&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;L&amp;rsquo;idée est :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;de &lt;strong&gt;créer un nom de tag&lt;/strong&gt; pour l&amp;rsquo;image (variable IMAGE_TAG),&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;récupérer l&amp;rsquo;image précédente&lt;/strong&gt; - puisque les étapes d&amp;rsquo;un fichier &lt;em&gt;.gitlab-ci.yml&lt;/em&gt; s&amp;rsquo;exécutent dans des conteneurs isolés les uns des autres,&lt;/li&gt;
&lt;li&gt;apposer un &lt;strong&gt;nouveau tag&lt;/strong&gt; sur l&amp;rsquo;image récupérée,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;publier le résultat&lt;/strong&gt; en poussant l&amp;rsquo;image ainsi étiquetée.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ceci ne s&amp;rsquo;exécute que si la branche est nommée &lt;strong&gt;main&lt;/strong&gt;. Donc chaque commit sur cette branche générera une image Docker et un tag.&lt;/p&gt;
&lt;h2 id=&#34;ordre-dexécution-des-étapes&#34;&gt;Ordre d&amp;rsquo;exécution des étapes&lt;/h2&gt;
&lt;p&gt;Afin que les deux étapes précédentes s&amp;rsquo;exécutent dans un certain ordre, &lt;strong&gt;ne pas oublier les lignes suivantes&lt;/strong&gt; dans le fichier &lt;em&gt;.gitlab-ci.yml&lt;/em&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;stages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;push&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;comme-si-ça-ne-suffisait-pas&#34;&gt;Comme si ça ne suffisait pas…&lt;/h2&gt;
&lt;p&gt;En outre, voici d&amp;rsquo;&lt;strong&gt;autres éléments à rajouter&lt;/strong&gt; dans son fichier &lt;em&gt;.gitlab-ci.yml&lt;/em&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DOCKER_HOST&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;tcp://docker:2376&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DOCKER_TLS_CERTDIR&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/certs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ces lignes permettent de renseigner un &lt;strong&gt;autre accès à l&amp;rsquo;API Docker&lt;/strong&gt; pour lancer les commandes &lt;code&gt;docker&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;les-composants-réutilisables&#34;&gt;Les composants réutilisables&lt;/h1&gt;
&lt;p&gt;Gitlab CI offre la possibilité d&amp;rsquo;utiliser des &lt;a href=&#34;https://docs.gitlab.com/ci/components/&#34;&gt;&lt;strong&gt;composants réutilisables&lt;/strong&gt;&lt;/a&gt; pour agrémenter les étapes de son fichier &lt;em&gt;.gitlab-ci.yml&lt;/em&gt;. Ceci évite de réinventer la roue (en codant soi-même).&lt;/p&gt;
&lt;p&gt;Plusieurs composants sont disponibles sur la &lt;a href=&#34;https://gitlab.com/components&#34;&gt;page Gitlab components&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Exemple d&amp;rsquo;utilisation d&amp;rsquo;un composant :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;include&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;component&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;gitlab.com/components/container-scanning/container-scanning@5.1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;C&amp;rsquo;est très utile dans certaines situations comme pour tester des fichiers Terraform (avec &lt;a href=&#34;https://gitlab.com/components/opentofu&#34;&gt;le composant OpenTofu&lt;/a&gt;), &lt;a href=&#34;https://gitlab.com/components/go&#34;&gt;le composant Go&lt;/a&gt;, &lt;a href=&#34;https://gitlab.com/components/go&#34;&gt;le composant Rust&lt;/a&gt; ou même utiliser les &lt;a href=&#34;https://gitlab.com/components/autodevops&#34;&gt;fonctionnalités Autodevops de Gitlab&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Au premier abord Gitlab CI paraît complexe et maigre en fonctionnalités. Cependant la lecture de la &lt;strong&gt;documentation (très fournie&lt;/strong&gt; !) donne rapidement un aperçu bien plus avantageux de cet outil. On y découvre les composants réutilisables, les mots clés &lt;code&gt;image&lt;/code&gt;, &lt;code&gt;variables&lt;/code&gt;, &lt;code&gt;before_script&lt;/code&gt;, les artefacts (sorties), les variables globales, le déploiement de sites statiques et j&amp;rsquo;en passe !&lt;/p&gt;
&lt;p&gt;Certaines difficultés telles que Docker viennent s&amp;rsquo;immiscer dans nos essais. Mais &lt;strong&gt;une fois les obstacles franchis c&amp;rsquo;est un outil très satisfaisant&lt;/strong&gt;. Je l&amp;rsquo;apprécie.&lt;/p&gt;
&lt;p&gt;Je serais ravi de tomber plus souvent sur des articles décrivant ses fonctionnalités. J&amp;rsquo;espère participer à une diffusion plus grande de la connaissance Gitlab CI et, qui sait, peut-être partagerais-je prochainement d&amp;rsquo;autres astuces ?&lt;/p&gt;
</description>
    </item>
    
    <item>
	    <title>Mes conseils pour réussir une formation Bootcamp</title>
      <link>https://olivier.dossmann.net/2024/10/mes_conseils_pour_reussir_une_formation_bootcamp/</link>
      <pubDate>Sun, 13 Oct 2024 10:14:59 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2024/10/mes_conseils_pour_reussir_une_formation_bootcamp/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Il y a peu je commençais une &lt;strong&gt;formation&lt;/strong&gt; chez &lt;a href=&#34;https://datascientest.com/&#34;&gt;DataScientest&lt;/a&gt;. &lt;strong&gt;En Bootcamp&lt;/strong&gt;. Ce format est l&amp;rsquo;équivalent d&amp;rsquo;un &lt;strong&gt;temps complet&lt;/strong&gt; (lundi à vendredi de 8h à 18h) passé sur le contenu du programme pédagogique. Durée prévue dans ma situation : 3 mois.&lt;/p&gt;
&lt;p&gt;Ce temps est nécessaire pour apprendre les différentes notions. C&amp;rsquo;est à la fois long et court : &lt;strong&gt;c&amp;rsquo;est dense&lt;/strong&gt; et le temps accordé est parfois « tout juste » pour lire. Alors comment tenir ce &lt;strong&gt;Marathon de 3 mois&lt;/strong&gt; ?&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;aborderais dans un premier temps les éléments qui m&amp;rsquo;ont permis d&amp;rsquo;organiser mon plan de la semaine. Après quoi j&amp;rsquo;aborderais des sujets proches du contenu des cours comme les exercices et les examens. Finalement je donnerais des astuces diverses que j&amp;rsquo;ai listées au fur et à mesure de mon avancée dans l&amp;rsquo;aventure. Cette liste risque donc de s&amp;rsquo;allonger avec le temps !&lt;/p&gt;
&lt;p&gt;À noter que &lt;strong&gt;ces conseils sont forcément emprunts de mon expérience&lt;/strong&gt; de vie, mes compétences et mes particularités (la folie, ça compte ? &amp;#x1f914;)&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/humains/deep_work.jpg&#34; alt=&#34;Un homme travaillant avec un outil ressemblant à un marteau&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://flickr.com/photos/adouea/43082145135/&#34;&gt;profil de Aurélien Adoue sur Flickr&lt;/a&gt;&lt;/em&gt; sous Licence Attribution 2.0 Generic.&lt;/p&gt;
&lt;h1 id=&#34;organisation&#34;&gt;Organisation&lt;/h1&gt;
&lt;p&gt;1 mois que j&amp;rsquo;ai commencé la formation. Une &lt;strong&gt;durée prévue de 3 mois&lt;/strong&gt;. &lt;strong&gt;Une vie à mener à côté&lt;/strong&gt;. &lt;strong&gt;Des objectifs professionnels&lt;/strong&gt; en lien avec le résultat de ce Bootcamp. Vous ne pouvez pas vous pointer les mains dans les poches.&lt;/p&gt;
&lt;p&gt;Il est évident qu&amp;rsquo;&lt;strong&gt;il faut un plan&lt;/strong&gt;. Tous les conseils pointent sur la même chose : il faut &lt;strong&gt;compartimenter son temps&lt;/strong&gt;. Et s&amp;rsquo;y tenir ; oui &lt;strong&gt;s&amp;rsquo;y tenir&lt;/strong&gt;. Faites-le suivant votre vie et vos possibilités. Mais tenez-y vous ! Et mettez au courant votre entourage de votre planning.&lt;/p&gt;
&lt;h2 id=&#34;mon-planning&#34;&gt;Mon planning&lt;/h2&gt;
&lt;p&gt;Dans mon cas, j&amp;rsquo;ai opté pour le planning suivant :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les &lt;strong&gt;matins du lundi au jeudi&lt;/strong&gt; : lecture des &lt;strong&gt;nouveaux cours&lt;/strong&gt;. Apprentissage et exercices, voire &lt;strong&gt;examens&lt;/strong&gt; ;&lt;/li&gt;
&lt;li&gt;les &lt;strong&gt;après-midi du lundi au jeudi&lt;/strong&gt; : &lt;strong&gt;révision des cours&lt;/strong&gt; lus les jours précédents (parfois semaines précédentes), sinon faire des &lt;strong&gt;exercices&lt;/strong&gt; ;&lt;/li&gt;
&lt;li&gt;le &lt;strong&gt;vendredi&lt;/strong&gt; : &lt;strong&gt;mise en pratique&lt;/strong&gt; des outils/notions appri(e)s(es) sur des projets personnels.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;De cette manière &lt;strong&gt;la nouveauté arrive quand je suis frais, c&amp;rsquo;est à dire le matin&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Viens ensuite l&amp;rsquo;après-midi, après le repas, où je suis moins attentif que le matin. Idéal pour des révisions sur des sujets déjà abordés les jours précédents. Et cela fait une fin de journée plus tranquille que le matin.&lt;/p&gt;
&lt;p&gt;Une révision passe par la rédaction de « fiches » de synthèse pour créer des récapitulatifs de ce qui a été vu. Parfois je dessine des &lt;a href=&#34;https://fr.wikipedia.org/wiki/Carte_heuristique&#34;&gt;cartes heuristiques&lt;/a&gt; : plus parlantes pour moi.&lt;/p&gt;
&lt;p&gt;Pendant la lecture des cours &lt;strong&gt;je note des idées d&amp;rsquo;utilisation des outils découverts&lt;/strong&gt; (en somme des projets qui germent dans ma tête). Ce qui me permet d&amp;rsquo;aborder le vendredi un projet réfléchi pendant la semaine. Exemple : à la lecture du contenu, j&amp;rsquo;ai noté qu&amp;rsquo;il y avait beaucoup d&amp;rsquo;abréviations. Par ailleurs, un des modules du cours apprend à utiliser un outil de création d&amp;rsquo;API. Quoi de mieux que de créer une API pour lister les abréviations ? Et hop!, un projet à faire le vendredi.&lt;/p&gt;
&lt;p&gt;Autre exemple : on apprend le scripting Bash ? Quoi de mieux que de faire un outil pour automatiser l&amp;rsquo;installation de nos logiciels habituels sur les machines virtuelles fournies par le centre de formation ? Ou bien simplifier la vie en ajoutant des raccourcis (alias) Bash pour les commandes usuelles pendant les cours ?&lt;/p&gt;
&lt;p&gt;On apprend la méthode ETL (Extract, Transform, Load) sur des API ? Utilisons notre API des abréviations pour extraire les données !&lt;/p&gt;
&lt;p&gt;Que faire une fois les données extraites ? On a appris à utiliser - en bonus - SQLAlchemy (bibliothèque pour faire des requêtes sur une base de données), pourquoi ne pas l&amp;rsquo;utiliser pour insérer les données extraites de l&amp;rsquo;API pour les charger dans une base de données à nous ?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mais en dehors de ces moments, que fais-tu Olivier ?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;hors-planning&#34;&gt;Hors planning&lt;/h2&gt;
&lt;p&gt;Si le planning existe, c&amp;rsquo;est pour une raison : &lt;strong&gt;il est nécessaire d&amp;rsquo;avoir une vie à côté !&lt;/strong&gt; Il faut du temps pour :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la &lt;strong&gt;famille&lt;/strong&gt; (conjoint(e), enfants, parents, etc.),&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;des pauses&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;avoir &lt;strong&gt;du temps à soi&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;dormir&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;manger&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Réellement, &lt;strong&gt;il FAUT ce temps&lt;/strong&gt; pour votre famille et vous !&lt;/p&gt;
&lt;p&gt;La famille apporte un entourage (indirectement ça peut être de la confiance en soi), les pauses un souffle pour votre cerveau, le temps à soi pour se retrouver, dormir pour ranger les informations dans votre cerveau et manger pour redonner de l&amp;rsquo;énergie à votre corps !&lt;/p&gt;
&lt;p&gt;Chacun de ces éléments va permettre de franchir plus facilement les obstacles de votre parcours en Bootcamp. D&amp;rsquo;où le côté strict des horaires que vous vous donnez.&lt;/p&gt;
&lt;p&gt;Ainsi après une matinée de lecture de nouveaux cours, vers midi, je m&amp;rsquo;arrête. Et je passe à autre chose : le repas, une pause et un repos &lt;strong&gt;allongé sur le dos&lt;/strong&gt; pendant 10 mn environ. Avant de recommencer sur l&amp;rsquo;après-midi avec les révisions de la veille.&lt;/p&gt;
&lt;p&gt;Après 17h ? Je m&amp;rsquo;arrête également. Je passe aux tâches quotidiennes, de la famille et du repas du soir. Un peu de détente. Un bon gros sommeil de plus de 8h.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Et la journée recommence.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Le week-end ? Pas de formation.&lt;/strong&gt; La famille, les amis, du temps pour notre conjoint, pour soi, etc. On fait toutes ces choses qui donnent &lt;strong&gt;de l&amp;rsquo;énergie&lt;/strong&gt; et remplissent &lt;strong&gt;notre cœur&lt;/strong&gt;, &lt;strong&gt;notre corps&lt;/strong&gt; et &lt;strong&gt;notre moral&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;La partie organisation est très importante, elle va définir si vous aurez la tête sous l&amp;rsquo;eau ou pas. Prenez donc le temps de définir tout ça. Respectez votre planning et les personnes qui vous entourent. Par ailleurs, ce n&amp;rsquo;est qu&amp;rsquo;une seule clé parmi d&amp;rsquo;autres : pour que cela fonctionne il est nécessaire d&amp;rsquo;être efficace lors de sa période de travail. C&amp;rsquo;est ce que nous allons voir dans le prochain chapitre.&lt;/p&gt;
&lt;h1 id=&#34;travail-efficace&#34;&gt;Travail efficace&lt;/h1&gt;
&lt;p&gt;Il n&amp;rsquo;y a pas de secrets selon moi, &lt;strong&gt;un travail efficace est&lt;/strong&gt; déterminé par :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;un &lt;strong&gt;environnement&lt;/strong&gt; spécifique de travail,&lt;/li&gt;
&lt;li&gt;une &lt;strong&gt;technique d&amp;rsquo;assimilation&lt;/strong&gt; particulière,&lt;/li&gt;
&lt;li&gt;et une façon d&amp;rsquo;agir durant &lt;strong&gt;les examens&lt;/strong&gt; chronométrés.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Je vais donc vous parler de chacun des ces points en donnant quelques astuces issues d&amp;rsquo;études faites sur la question.&lt;/p&gt;
&lt;h2 id=&#34;point-1-lenvironnement-de-travail&#34;&gt;Point 1 : l&amp;rsquo;environnement de travail&lt;/h2&gt;
&lt;p&gt;À la lecture du livre &lt;a href=&#34;https://calnewport.com/deep-work-rules-for-focused-success-in-a-distracted-world/&#34;&gt;Deep work, retrouver la concentration dans un monde de distractions&lt;/a&gt; écrit par Cal NEWPORT (un professeur dans les sciences informatiques du MIT - rien que ça!), j&amp;rsquo;ai bien compris qu&amp;rsquo;il fallait un environnement &lt;strong&gt;sans distractions&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Exit les &lt;strong&gt;téléphones mobiles&lt;/strong&gt; : on le met &lt;strong&gt;sur mode avion&lt;/strong&gt;. On s&amp;rsquo;enferme dans une pièce, à clé. On mobilise toutes nos ressources pour se concentrer sur la tâche à accomplir : apprendre les cours.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Toute perturbation est à proscrire&lt;/strong&gt; et malheureusement pour certains : la musique en fait partie. Il semble que des études ont déterminé que cela activait des zones du cerveau qui empêchent une concentration complète.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;idée du livre « Deep work » est que &lt;strong&gt;si vous êtes concentrés vous prendrez moins de temps à travailler&lt;/strong&gt;. Ce qui me semble tout à fait adapté pour une formation en Bootcamp, n&amp;rsquo;est-ce pas ?&lt;/p&gt;
&lt;h2 id=&#34;point-2-assimiler-les-cours&#34;&gt;Point 2 : assimiler les cours&lt;/h2&gt;
&lt;p&gt;Là encore, les scientifiques ont étudié la question. Et c&amp;rsquo;est au travers d&amp;rsquo;une &lt;strong&gt;&lt;a href=&#34;https://scienceetonnante.com/2023/09/01/mieux-apprendre-etudier-les-vraies-techniques-scientifiques/&#34;&gt;vidéo de Science étonnante concernant les (vraies) techniques pour mieux apprendre et étudier&lt;/a&gt;&lt;/strong&gt; que j&amp;rsquo;ai pu améliorer mon apprentissage.&lt;/p&gt;
&lt;p&gt;Je vous conseille de regarder la vidéo - YouTube - et d&amp;rsquo;imaginer une nouvelle façon d&amp;rsquo;étudier, de réviser et de travailler.&lt;/p&gt;
&lt;p&gt;De mon côté j&amp;rsquo;ai opté pour &lt;strong&gt;la relecture régulière&lt;/strong&gt;, la lecture &lt;strong&gt;de plusieurs cours&lt;/strong&gt; qui font souvent &lt;strong&gt;des liens sur le domaine étudié&lt;/strong&gt; et &lt;strong&gt;la mise en pratique&lt;/strong&gt; par des cas concrets de la vie courante pour s&amp;rsquo;entraîner avec les outils étudiés. J&amp;rsquo;en parlais tout à l&amp;rsquo;heure : la création d&amp;rsquo;une API, l&amp;rsquo;extraction des données de cette dernière pour les introduire ensuite dans une autre base de données sous un autre format.&lt;/p&gt;
&lt;p&gt;À noter que plus loin dans cet article je vous demanderais de ne pas suivre de vidéos YouTube pendant vos études Bootcamp, je ne suis pas schizophrène : considérez cette vidéo comme l&amp;rsquo;exception qui confirme la règle &amp;#x1f603; .&lt;/p&gt;
&lt;h2 id=&#34;point-3-les-examens&#34;&gt;Point 3 : les examens&lt;/h2&gt;
&lt;p&gt;Certains examens sont chronométrés. Ce qui peut très vite être déstabilisant !&lt;/p&gt;
&lt;p&gt;Je propose plusieurs choses pour s&amp;rsquo;en sortir :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Rien de mieux que &lt;strong&gt;la préparation&lt;/strong&gt; : si vous avez fait les cours régulièrement et &lt;strong&gt;que vous avez révisé&lt;/strong&gt; 1 jour après, 2 jours après, 1 semaine après, vous retiendrez bien mieux les cours ;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Faites des exercices&lt;/strong&gt; avant et sentez-vous un minimum à l&amp;rsquo;aise, &lt;strong&gt;travaillez les points sensibles&lt;/strong&gt; ;&lt;/li&gt;
&lt;li&gt;Lors des examens : &lt;strong&gt;ouvrez en avance les documentations&lt;/strong&gt; qui vous aident ;&lt;/li&gt;
&lt;li&gt;Dans les examens, optez pour &lt;strong&gt;des noms de variables courts&lt;/strong&gt; : plus vous rallongez le nom des fonctions et des variables, plus vous aurez à taper du code. Indirectement vous prenez un temps fou pour rédiger au lieu de réfléchir !&lt;/li&gt;
&lt;li&gt;Pour les examens, &lt;strong&gt;préparez&lt;/strong&gt; déjà à côté vos codes sur le sujet : c&amp;rsquo;est &lt;strong&gt;votre code, celui qui vous ressemble&lt;/strong&gt;. Rien n&amp;rsquo;interdit un copier-coller de votre propre travail !&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Avec ces 3 points, vous devriez déjà avoir &lt;strong&gt;de bonnes bases&lt;/strong&gt; pour aborder la formation. Il y a d&amp;rsquo;autres astuces diverses que nous allons découvrir maintenant.&lt;/p&gt;
&lt;h1 id=&#34;diverses-astuces&#34;&gt;Diverses astuces&lt;/h1&gt;
&lt;p&gt;Ne sachant dans quelles catégories mettre ces astuces, mais considérant ces dernières comme tout aussi importantes, je vous les dépose là. Piochez selon vos envies ;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Revoyez chaque semaine le planning&lt;/strong&gt; que vous allez suivre : quel cours étudier chaque jour. Prenez en compte les sujets sur lesquels vous avez déjà des connaissances pour passer plus de temps sur ceux que vous ne connaissez pas ;&lt;/li&gt;
&lt;li&gt;Ne prenez &lt;strong&gt;des notes qu&amp;rsquo;à une seconde lecture&lt;/strong&gt; (lors de révisions par exemple) : sinon vous allez passer trop de temps sur un cours ;&lt;/li&gt;
&lt;li&gt;Si vous avez un &lt;strong&gt;souci logiciel&lt;/strong&gt; qui empêche de travailler : &lt;strong&gt;passez à autre chose&lt;/strong&gt; !&lt;/li&gt;
&lt;li&gt;Quand vous revenez sur un souci logiciel - plus tard - si vous ne réussisez pas mieux, &lt;strong&gt;utilisez &lt;a href=&#34;https://chat.openai.com/&#34;&gt;ChatGPT&lt;/a&gt; pour décrire votre problème&lt;/strong&gt;. Cet outil est plutôt efficace pour donner des pistes. Rappelez vous, &lt;strong&gt;ChatGPT est un assistant&lt;/strong&gt;, vous le dirigez. Ce n&amp;rsquo;est pas lui qui doit vous diriger. ;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;N&amp;rsquo;utilisez pas de vidéos pour apprendre&lt;/strong&gt; - YouTube ou autre - c&amp;rsquo;est une &lt;strong&gt;perte de temps considérable&lt;/strong&gt;. Pourquoi ? Tout simplement car vous ne pourrez pas voir rapidement si la vidéo vous apporte quelque chose de concret ou non. Et parfois ce qu&amp;rsquo;ils disent est tout bonnement faux ! Cela vous apporte plus de confusion qu&amp;rsquo;autre chose. En revanche chez DataScientest ils ont des vidéos de cours. Cela apporte généralement quelque chose de concret et de vrai ;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lisez de la documentation&lt;/strong&gt; des outils utilisés : elles ne mentent pas. Elles décrivent. Et peut-être retiendrez-vous des options qui vous feront gagner plus tard un temps fou !&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restez humbles&lt;/strong&gt; : même si vous maîtrisez un sujet, vous trouverez souvent des nouveautés et des détails que vous ne connaissiez pas dans les cours ;&lt;/li&gt;
&lt;li&gt;Si vous avez la possibilité, &lt;strong&gt;apprenez à utiliser des dépôts Git rapidement pour enregistrer votre travail&lt;/strong&gt; sur les machines virtuelles distantes proposées par la formation. Cela vous évitera de mauvaises surprises quand les machines se réinitialisent…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si jamais je trouve d&amp;rsquo;autres astuces je les rajouterai ici.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Cette formation m&amp;rsquo;a permis de travailler mon environnement, mes méthodes de travail et découvrir des astuces pour &lt;strong&gt;être plus efficace en journée&lt;/strong&gt;. Et cela &lt;strong&gt;sans mettre de côté la famille&lt;/strong&gt; et la maison. Ce qui &lt;strong&gt;donne de l&amp;rsquo;énergie pour continuer chaque semaine&lt;/strong&gt; de travailler.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;C&amp;rsquo;est un cercle vertueux&lt;/strong&gt; que je conseille à chacun pour améliorer son quotidien et &lt;strong&gt;être plus productif&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Je souhaite de tout cœur &lt;strong&gt;que chacun trouve son équilibre&lt;/strong&gt; dans sa vie et réussisse sa formation en Bootcamp. Bonne chance à vous et bon travail !&lt;/p&gt;
</description>
    </item>
    
    <item>
	    <title>Cookiecutter-trognon pour initialiser mes scripts Bash</title>
      <link>https://olivier.dossmann.net/2024/04/cookiecutter_pour_initialiser_mes_scripts_bash/</link>
      <pubDate>Sun, 28 Apr 2024 13:20:47 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2024/04/cookiecutter_pour_initialiser_mes_scripts_bash/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Pour la petite histoire, l&amp;rsquo;année dernière je lisais l&amp;rsquo;&lt;a href=&#34;https://www.deblan.io/post/647/modele-pour-demarrer-script-shell&#34;&gt;article de deblan sur la création d&amp;rsquo;un modèle de script Shell&lt;/a&gt; sur le &lt;a href=&#34;https://www.journalduhacker.net/&#34;&gt;journalduhacker&lt;/a&gt;. Cela m&amp;rsquo;a rappelé que tôt ou tard dans &lt;strong&gt;la quête de l&amp;rsquo;automatisation&lt;/strong&gt; on arrive toujours à faire &lt;strong&gt;nos propres modèles de scripts&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;La plupart de &lt;strong&gt;mes projets utilisent&lt;/strong&gt; le modèle de script &lt;a href=&#34;https://github.com/blankoworld/trognon&#34;&gt;&lt;strong&gt;Trognon&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Comment, en partant de ce modèle, pourrais-je automatiser la création de nouvelles commandes ? C&amp;rsquo;est là qu&amp;rsquo;entre en jeu &lt;a href=&#34;https://cookiecutter.readthedocs.io/en/stable/&#34;&gt;cookiecutter&lt;/a&gt;, une commande et une méthode permettant de &lt;strong&gt;transformer n&amp;rsquo;importe lequel de vos projet en template&lt;/strong&gt; pour les suivants !&lt;/p&gt;
&lt;p&gt;Nous commencerons par voir le résultat de l&amp;rsquo;adaptation d&amp;rsquo;un script avec &lt;a href=&#34;https://cookiecutter.readthedocs.io/en/stable/&#34;&gt;cookiecutter&lt;/a&gt;. Ensuite nous verrons ce qu&amp;rsquo;est &lt;a href=&#34;https://cookiecutter.readthedocs.io/en/stable/&#34;&gt;cookiecutter&lt;/a&gt;. Finalement nous expliquerons comment adapter son projet avec &lt;a href=&#34;https://cookiecutter.readthedocs.io/en/stable/&#34;&gt;cookiecutter&lt;/a&gt; en présentant le cas pratique de &lt;a href=&#34;https://github.com/blankoworld/cookiecutter-trognon&#34;&gt;cookiecutter-trognon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/objets/lapins_chocolat.jpg&#34; alt=&#34;Des lapins de Pâques en chocolat, industrialisés et dupliqués à l&amp;rsquo;infini&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://flickr.com/photos/cogdog/52726715586/&#34;&gt;profil de Alan Levine sur Flickr&lt;/a&gt;&lt;/em&gt; sous Domaine public.&lt;/p&gt;
&lt;h1 id=&#34;le-résultat-cookiecutter-trognon&#34;&gt;Le résultat : cookiecutter-trognon&lt;/h1&gt;
&lt;p&gt;Pour une fois nous commencerons par la fin, c&amp;rsquo;est à dire le résultat ! &lt;strong&gt;L&amp;rsquo;automatisation de Trognon a donné un dépôt&lt;/strong&gt; : &lt;a href=&#34;https://github.com/blankoworld/cookiecutter-trognon&#34;&gt;cookiecutter-trognon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Grâce à lui, créer un nouveau script Bash suivant le modèle de Trognon revient à taper les commandes suivantes :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Installe cookiecutter sur notre machine (à ne faire que la première fois)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipx install cookiecutter
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Utilise mon dépôt Github de cookiecutter-trognon comme modèle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cookiecutter gh:blankoworld/cookiecutter-trognon
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ensuite 2 questions sont posées pour définir :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;le &lt;strong&gt;nom du dossier&lt;/strong&gt; dans lequel ma commande se trouvera&lt;/li&gt;
&lt;li&gt;le &lt;strong&gt;nom&lt;/strong&gt; souhaité pour la &lt;strong&gt;commande&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Évidemment j&amp;rsquo;ai défini les questions à poser et ce que je faisais des réponses dans le résultat. C&amp;rsquo;est là tout l&amp;rsquo;intérêt de cookiecutter : &lt;strong&gt;vous définissez les questions à poser, les réponses possibles&lt;/strong&gt; s&amp;rsquo;il en est, quoi faire des réponses et &lt;strong&gt;où les utiliser dans vos templates&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Voyons donc cookiecutter.&lt;/p&gt;
&lt;h1 id=&#34;présentation-de-cookiecutter&#34;&gt;Présentation de cookiecutter&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://cookiecutter.readthedocs.io/en/stable/&#34;&gt;cookiecutter&lt;/a&gt; est &lt;strong&gt;un outil Python qui duplique un répertoire&lt;/strong&gt;, vous pose des questions et modifie le duplicat en remplaçant certaines chaînes de caractères par les réponses données aux questions.&lt;/p&gt;
&lt;p&gt;Il sait agir de manière conditionnelle : c&amp;rsquo;est-à-dire qu&amp;rsquo;il peut aussi &lt;strong&gt;ajouter/enlever des pans de code/texte en fonction de la valeur d&amp;rsquo;une variable&lt;/strong&gt;. Ceci grâce au &lt;a href=&#34;https://jinja.palletsprojects.com/&#34;&gt;moteur de template Jinja&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Autrement dit : vous définissez les fichiers dont vous avez besoin (parfois un copier/coller suffit), puis vous insérez dans vos fichiers des chaînes de caractères que vous souhaitez remplacer dans le projet. Vous pouvez également définir des valeurs conditionnelles. Par exemple : si je souhaite avoir une licence MIT, alors le fichier LICENSE contiendra un certain texte. Si je choisis la licence &lt;a href=&#34;https://fr.wikipedia.org/wiki/WTFPL&#34;&gt;LPRÀB/WTFPL&lt;/a&gt;, alors j&amp;rsquo;aurais un autre texte.&lt;/p&gt;
&lt;p&gt;Un exemple concret serait plus parlant, essayons avec &lt;a href=&#34;https://github.com/blankoworld/cookiecutter-trognon&#34;&gt;cookiecutter-trognon&lt;/a&gt; !&lt;/p&gt;
&lt;h1 id=&#34;comment-transformer-trognon-en-cookiecutter-trognon&#34;&gt;Comment transformer Trognon en cookiecutter-trognon ?&lt;/h1&gt;
&lt;h2 id=&#34;en-rapide&#34;&gt;En rapide&lt;/h2&gt;
&lt;p&gt;Pour rendre un projet compatible avec cookiecutter, il va falloir suivre quelques étapes clés :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Créer un &lt;strong&gt;nouveau répertoire&lt;/strong&gt; pour votre projet,&lt;/li&gt;
&lt;li&gt;Y créer un fichier nommé &lt;strong&gt;cookiecutter.json&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;Créer &lt;strong&gt;un répertoire nommé &lt;code&gt;{{ cookiecutter.project_slug }}&lt;/code&gt;&lt;/strong&gt; (oui oui, &lt;strong&gt;AVEC&lt;/strong&gt; les accolades),&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Déposer les fichiers nécessaires&lt;/strong&gt; au projet &lt;strong&gt;dans le répertoire &lt;code&gt;{{ cookiecutter.project_slug }}&lt;/code&gt;&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;Remplacer dans les fichiers tous les mots à adapter à chaque nouveau projet : pour cela utiliser les mots clés fournis dans le fichier &lt;em&gt;cookiecutter.json&lt;/em&gt; (&lt;strong&gt;variables&lt;/strong&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Dans le cas de Trognon, j&amp;rsquo;ai déposé les fichiers du projet dans le répertoire &lt;code&gt;{{ cookiecutter.project_slug }}&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;cookiecutterjson-la-configuration-du-projet&#34;&gt;cookiecutter.json, la configuration du projet&lt;/h2&gt;
&lt;p&gt;J&amp;rsquo;ai ensuite rempli le fichier &lt;code&gt;cookiecutter.json&lt;/code&gt; tel que montré ici :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;project_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Mon projet&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;__project_slug&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ cookiecutter.project_name.lower().replace(&amp;#39; &amp;#39;, &amp;#39;_&amp;#39;).replace(&amp;#39;-&amp;#39;, &amp;#39;_&amp;#39;) }}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;command_shortname&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CommandePrincipale&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;__command_slug&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ cookiecutter.command_shortname.lower().replace(&amp;#39; &amp;#39;, &amp;#39;_&amp;#39;).replace(&amp;#39;-&amp;#39;, &amp;#39;_&amp;#39;) }}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;__prompts__&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;project_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Choisissez un nom de projet court&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;command_shortname&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Que voudriez-vous comme nom court de commande ?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Je défini des variables&lt;/strong&gt; comme :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;project_name&lt;/strong&gt; : le nom du projet, avec comme valeur par défaut &lt;code&gt;Mon projet&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;command_shortname&lt;/strong&gt; : le nom de la commande Bash que nous utiliserons.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;D&amp;rsquo;autres variables ne demanderont rien à l&amp;rsquo;utilisateur car elles commencent par deux espaces soulignes &lt;code&gt;__&lt;/code&gt;. Je parle bien entendu de &lt;code&gt;__project_slug&lt;/code&gt;, &lt;code&gt;__command_slug&lt;/code&gt; et &lt;code&gt;__prompts__&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Cependant &lt;code&gt;__prompts__&lt;/code&gt; a une particularité : il permet de &lt;strong&gt;personnaliser la question posée&lt;/strong&gt; pour chaque variable.&lt;/p&gt;
&lt;p&gt;Ainsi pour définir &lt;code&gt;project_name&lt;/code&gt;, l&amp;rsquo;utilisateur verra la question suivante : &lt;code&gt;Choisissez un nom de projet court&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;remplacer-des-mots-par-des-variables&#34;&gt;Remplacer des mots par des variables&lt;/h2&gt;
&lt;p&gt;Maintenant que le fichier &lt;code&gt;cookiecutter.json&lt;/code&gt; possède des mots clés spécifiques (des variables), nous allons pouvoir modifier les fichiers de notre projet pour contenir des « mots-clés ». Par exemple voici le début du fichier &lt;em&gt;README.md&lt;/em&gt; de Trognon (&lt;strong&gt;AVANT&lt;/strong&gt; modifications) :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Trognon

Un lanceur de commandes personnalisées pour votre projet de développement.

Exemple : 

# Affiche l&amp;#39;aide
./agnes help

# Installe votre projet (vous devez définir ce que `install` fait)
./agnes install

# créé un dump de la base de données
./agnes dump
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ce qui donne le fichier README.md suivant dans notre projet cookiecutter-trognon (&lt;strong&gt;APRÈS&lt;/strong&gt; modifications) :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# {{ cookiecutter.project_name }}

Un lanceur de commandes personnalisées pour votre projet de développement.

Exemple : 

# Affiche l&amp;#39;aide
./{{ cookiecutter.__command_slug }} help

# Installe votre projet (vous devez définir ce que `install` fait)
./{{ cookiecutter.__command_slug }} install

# créé un dump de la base de données
./{{ cookiecutter.__command_slug }} dump
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous avons ainsi remplacé respectivement le titre du fichier et les commandes d&amp;rsquo;exemple en &lt;code&gt;{{ cookiecutter.project_name }}&lt;/code&gt; et &lt;code&gt;{{ cookiecutter.__command_slug }}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Vous pouvez en savoir plus sur &lt;a href=&#34;https://cookiecutter.readthedocs.io/en/stable/index.html&#34;&gt;la documentation officielle de cookiecutter&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;J&amp;rsquo;espère qu&amp;rsquo;à travers cet article vous aurez compris l&amp;rsquo;&lt;strong&gt;avantage d&amp;rsquo;utiliser cookiecutter&lt;/strong&gt; et que vous &lt;strong&gt;envisagerez à l&amp;rsquo;avenir de l&amp;rsquo;intégrer dans votre processus d&amp;rsquo;automatisation&lt;/strong&gt; de la génération initiale de vos projets et de vos scripts.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;informatique énonce souvent d&amp;rsquo;éviter de réinventer la roue ; je pense que &lt;strong&gt;cookiecutter est l&amp;rsquo;outil indispensable&lt;/strong&gt; pour favoriser ce concept.&lt;/p&gt;
&lt;p&gt;Une fois ce processus de création automatisé, vous vous rendrez compte que vous générerez plus souvent des scripts/projets, que vous vous concentrerez uniquement sur le contenu du projet et pas sur tout l&amp;rsquo;environnement autour : c&amp;rsquo;est un gain de temps et de qualité ! Une &lt;strong&gt;belle valeur ajoutée&lt;/strong&gt; en somme.&lt;/p&gt;
</description>
    </item>
    
    <item>
	    <title>Vers quelle console se tourner en 2024 ?</title>
      <link>https://olivier.dossmann.net/2024/04/vers-quelle-console-se-tourner-en-2024/</link>
      <pubDate>Wed, 10 Apr 2024 16:24:18 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2024/04/vers-quelle-console-se-tourner-en-2024/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Après plusieurs échanges similaires avec des amis, il était temps de lister ce que je trouve intéressant et/ou problématique dans chacune des 3 consoles suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nintendo Switch&lt;/strong&gt; (Switch)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Microsoft Xbox Serie X&lt;/strong&gt; (Xbox)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sony Playstation 5 Standard FAT&lt;/strong&gt; (PS5)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ceci est mon avis, cela représente &lt;strong&gt;ce que je pense&lt;/strong&gt; sur ces dernières. Il reste &lt;strong&gt;à chacun de juger selon lui et suivant ses infos&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Je regarde essentiellement le coût de ces consoles et ce que nous avons à disposition. Si vous détestez voir des chiffres défiler, arrêtez la lecture de cet article &amp;#x1f609;. Par ailleurs chaque console représente un écosystème entier, il est difficile d&amp;rsquo;être réellement objectif dans leur comparaison, tant ils sont différents.&lt;/p&gt;
&lt;p&gt;Alerte spoiler : Cet article sera long.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/objets/rouages_lumineux.jpg&#34; alt=&#34;Rouages lumineux&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://flickr.com/photos/adouea/43889619445/&#34;&gt;profil de Aurélien Adoue sur Flickr&lt;/a&gt;&lt;/em&gt; sous licence CC BY 2.0.&lt;/p&gt;
&lt;h1 id=&#34;avant-de-commencer&#34;&gt;Avant de commencer&lt;/h1&gt;
&lt;p&gt;Dans cet article je comparerais plusieurs éléments comme :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;le &lt;strong&gt;prix d&amp;rsquo;achat&lt;/strong&gt; de la console&lt;/li&gt;
&lt;li&gt;l&amp;rsquo;&lt;strong&gt;abonnement&lt;/strong&gt; pour bénéficier de sauvegardes de ses parties (et parfois l&amp;rsquo;accès à un catalogue de jeux)&lt;/li&gt;
&lt;li&gt;la &lt;strong&gt;quantité de jeux disponibles&lt;/strong&gt; (la variété du catalogue de jeux vidéos par exemple)&lt;/li&gt;
&lt;li&gt;le &lt;strong&gt;prix des jeux d&amp;rsquo;occasion&lt;/strong&gt;, ce qui permet d&amp;rsquo;estimer l&amp;rsquo;accès aux jeux pour les petits budgets&lt;/li&gt;
&lt;li&gt;les &lt;strong&gt;problèmes matériels&lt;/strong&gt; connus qui peuvent engendrer un rachat de la console ou bien des accessoires&lt;/li&gt;
&lt;li&gt;le &lt;strong&gt;prix d&amp;rsquo;une manette&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je cherche plus ou moins à savoir ce qui pourrait - &lt;strong&gt;économiquement parlant&lt;/strong&gt; - être plus accessible. Autrement dit sur quelle console pourrais-je estimer pouvoir &lt;strong&gt;dépenser le moins d&amp;rsquo;argent par an pour jouer&lt;/strong&gt; et renouveler mon catalogue de jeux joués ? Évidemment &lt;strong&gt;les prix fluctuent beaucoup&lt;/strong&gt;, notamment pour les consoles PS5 et Xbox qui varient parfois de 50€ à 100€. À vos calculatrices !&lt;/p&gt;
&lt;p&gt;Nous commencerons avec la Nintendo Switch, puis la Microsoft Xbox Serie X et enfin la Sony Playstation 5 Standard FAT. &lt;strong&gt;Ce sont 3 consoles que j&amp;rsquo;ai eu en main, que j&amp;rsquo;ai pu tester&lt;/strong&gt; et où j&amp;rsquo;ai pu expérimenter quelques éléments &lt;strong&gt;entre 2 et 5 ans&lt;/strong&gt; (suivant les consoles).&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;insiste sur les modèles disposant d&amp;rsquo;un compartiment pour accueillir les jeux vidéos (lecteur DVD, slot pour des cartouches de jeu, etc.) car &lt;strong&gt;cela permet d&amp;rsquo;avoir accès à des jeux d&amp;rsquo;occasion&lt;/strong&gt; (donc coûter moins que les jeux neufs).&lt;/p&gt;
&lt;p&gt;Les 3 modèles visés/testés &lt;strong&gt;se branchent au minimum sur une télévision&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;On part du principe qu&amp;rsquo;&lt;strong&gt;on joue environ 500 heures par an&lt;/strong&gt;, c&amp;rsquo;est à dire &lt;strong&gt;environ 1h30 par jour&lt;/strong&gt;. Si les jeux prennent une cinquantaine d&amp;rsquo;heures à finir, on consommerait &lt;strong&gt;10 jeux par an&lt;/strong&gt;. Tout ceci est relatif et doit bien être pris en compte dans &lt;strong&gt;vos calculs&lt;/strong&gt;. C&amp;rsquo;est intéressant de faire le calcul pour soi, histoire de voir si le jeu vidéo est un loisir très dépensier dans VOTRE budget. Mine de rien, ça consomme de l&amp;rsquo;argent tout cela, comme nous le verrons ci-après !&lt;/p&gt;
&lt;h1 id=&#34;nintendo-switch&#34;&gt;Nintendo Switch&lt;/h1&gt;
&lt;h2 id=&#34;les-chiffres&#34;&gt;Les chiffres&lt;/h2&gt;
&lt;p&gt;Commençons par la plus ancienne console sur le marché : la Nintendo Switch.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prix d&amp;rsquo;&lt;strong&gt;achat&lt;/strong&gt; (sur Amazon) : &lt;strong&gt;~ 250€&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prix &lt;strong&gt;abonnement annuel&lt;/strong&gt; minimum : &lt;strong&gt;~ 20€&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Avantage abonnement : &lt;strong&gt;jeux NES, SNES et Gameboy (color)&lt;/strong&gt; (~ 30 jeux)&lt;/li&gt;
&lt;li&gt;Abonnement familial : &lt;strong&gt;~ 35€&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Manettes disponibles à l&amp;rsquo;achat : &lt;strong&gt;2&lt;/strong&gt; (gauche et droite, même si petites)&lt;/li&gt;
&lt;li&gt;Particularité : &lt;strong&gt;utilisable en console portable, prend peu de place&lt;/strong&gt; (~ 3h30 d&amp;rsquo;autonomie)&lt;/li&gt;
&lt;li&gt;Prix d&amp;rsquo;un jeu neuf : &lt;strong&gt;~ 50€&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prix du même jeu en occasion : &lt;strong&gt;~30&lt;/strong&gt; (varie en fonction des régions et de l&amp;rsquo;interlocuteur + capacité à discuter le prix)&lt;/li&gt;
&lt;li&gt;Prix d&amp;rsquo;une manette (simple) : &lt;strong&gt;~ 45€&lt;/strong&gt; à l&amp;rsquo;unité, ou &lt;strong&gt;~ 65€&lt;/strong&gt; les deux&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/materiel/nintendo_switch_detail.jpg&#34; alt=&#34;Console Nintento Switch™&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://www.flickr.com/photos/linsinchen/39571683174/&#34;&gt;profil de Sinchen.Lin sur Flickr&lt;/a&gt;&lt;/em&gt; sous licence CC BY 2.0.&lt;/p&gt;
&lt;h2 id=&#34;avantages&#34;&gt;Avantage(s)&lt;/h2&gt;
&lt;p&gt;L&amp;rsquo;avantage principal de cette console : elle est aussi &lt;strong&gt;portable&lt;/strong&gt;. C&amp;rsquo;est à dire qu&amp;rsquo;elle s&amp;rsquo;enlève du socle de la télévision pour être utilisable partout dans la maison (ou ailleurs). Sa &lt;strong&gt;batterie tient au moins 3h30&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Elle est &lt;strong&gt;relativement petite&lt;/strong&gt; pour une console de salon, ce qui fait un gain de place.&lt;/p&gt;
&lt;p&gt;Le &lt;strong&gt;catalogue des jeux est un des plus riches&lt;/strong&gt; et des plus complets. Avec des &lt;strong&gt;jeux variés&lt;/strong&gt; : il y en a pour tous les goûts ! Certaines exclusivités d&amp;rsquo;autres consoles sont portés sur la Nintendo Switch, ce qui est très plaisant.&lt;/p&gt;
&lt;h2 id=&#34;inconvénients&#34;&gt;Inconvénient(s)&lt;/h2&gt;
&lt;p&gt;Du fait de la « petitesse » de cette console, il y a une &lt;strong&gt;limitation sur le matériel embarqué&lt;/strong&gt;, notamment pour ce qui est du refroidissement de la carte graphique. Ceci implique des graphismes moins proches de la réalité (comparé à d&amp;rsquo;autres consoles).&lt;/p&gt;
&lt;p&gt;Cependant sachez qu&amp;rsquo;au lieu de se concentrer sur la parfaite illusion de réalité dans les jeux vidéos, les concepteurs de jeu peuvent &lt;strong&gt;s&amp;rsquo;atteler à la jouabilité&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Autre point négatif : le problème connu dit du « &lt;strong&gt;Joy-Con Drift&lt;/strong&gt; ». Après un certain temps d&amp;rsquo;utilisation, &lt;strong&gt;il arrive que la manette gauche pose problème&lt;/strong&gt; : le personnage que vous dirigez dans le jeu bouge tout seul. Bien que ce soit problématique, au lieu de racheter une manette &lt;strong&gt;il existe une solution « maison »&lt;/strong&gt; tel que vous pouvez le &lt;a href=&#34;https://www.tomsguide.fr/joy-con-drift-un-bout-de-carton-suffit-a-reparer-la-manette-de-la-nintendo-switch/&#34;&gt;lire dans l&amp;rsquo;article expliquant la solution avec… un bout de carton&lt;/a&gt; ! &lt;strong&gt;Cette solution ne fonctionnera pas avec une Nintendo Switch Lite&lt;/strong&gt; dont les manettes ne sont pas détachables.&lt;/p&gt;
&lt;h2 id=&#34;au-minimum-sans-jeux&#34;&gt;Au minimum (sans jeux)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;270€&lt;/strong&gt; (250€ HA + 20€ abonnement simple)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;20€&lt;/strong&gt; (20€ abonnement simple)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;au-minimum-avec-ha-de-jeux&#34;&gt;Au minimum (avec HA de jeux)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;770€&lt;/strong&gt; (250€ HA + 20€ abonnement simple + 10 jeux neufs × 50€)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;520€&lt;/strong&gt; (20€ abonnement simple + 10 jeux neufs × 50€)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;minimum-familial&#34;&gt;Minimum familial&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;785€&lt;/strong&gt; (250€ HA + 35€ abonnement familial + 10 jeux neufs × 50€)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;535€&lt;/strong&gt; (35€ abonnement familial + 10 jeux neufs × 50€)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;au-maximum-familial--pack-additionnel-à-70an&#34;&gt;Au maximum (familial + pack additionnel à 70€/an)&lt;/h2&gt;
&lt;p&gt;Avec le pack additionnel vous avez, en plus des jeux NES, SNES et GameBoy (color), un accès à :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;des jeux GameBoy Advance&lt;/li&gt;
&lt;li&gt;des jeux Nintendo 64&lt;/li&gt;
&lt;li&gt;des jeux Mega Drive&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ainsi :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;320€&lt;/strong&gt; (250€HA + 70€ abonnement familial + pack additionnel)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;70€&lt;/strong&gt; (70€ abonnement familial + pack additionnel)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion-intermédiaire---switch&#34;&gt;Conclusion intermédiaire - Switch&lt;/h2&gt;
&lt;p&gt;On notera :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la différence &lt;strong&gt;négligeable&lt;/strong&gt; entre abonnement simple et familial : très rentable quand nous sommes plusieurs à la maison (même avec chacun une console)&lt;/li&gt;
&lt;li&gt;le &lt;strong&gt;pack aditionnel&lt;/strong&gt; (abonnement supplémentaire) permet de jouer à des jeux rétros &lt;strong&gt;mais pas avec des jeux modernes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;le catalogue (Nintendo eShop) est &lt;strong&gt;large, varié, avec des réductions fréquentes de 80%&lt;/strong&gt; sur de bons jeux&lt;/li&gt;
&lt;li&gt;vous jouez sur la TV et quelqu&amp;rsquo;un de la famille voudrait regarder la TV ? Pas de souci : vous enlevez la console du socle et pouvez continuer votre partie ailleurs. Le côté portable de cette console est très pratique !&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La Nintendo Switch est donc une console bas prix avec beaucoup de possibilités !&lt;/p&gt;
&lt;h1 id=&#34;microsoft-xbox-série-x&#34;&gt;Microsoft Xbox Série X&lt;/h1&gt;
&lt;h2 id=&#34;les-chiffres-1&#34;&gt;Les chiffres&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Prix d&amp;rsquo;&lt;strong&gt;achat&lt;/strong&gt; (sur Amazon) : &lt;strong&gt;~ 550€&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prix &lt;strong&gt;abonnement annuel&lt;/strong&gt; minimum : &lt;strong&gt;~ 84€&lt;/strong&gt; (7€ × 12 mois)&lt;/li&gt;
&lt;li&gt;Avantage abonnement : &lt;strong&gt;petit catalogue de jeux&lt;/strong&gt; (~ 25 jeux)&lt;/li&gt;
&lt;li&gt;Abonnement familial : &lt;strong&gt;aucun&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Manettes disponibles à l&amp;rsquo;achat : &lt;strong&gt;1&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Particularité : &lt;strong&gt;prend peu de place, même debout&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prix d&amp;rsquo;un jeu neuf : &lt;strong&gt;~80€&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prix du même jeu en occasion : &lt;strong&gt;~40&lt;/strong&gt; (varie en fonction des régions et de l&amp;rsquo;interlocuteur + capacité à discuter le prix)&lt;/li&gt;
&lt;li&gt;Prix d&amp;rsquo;une manette : &lt;strong&gt;~ 60€&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/materiel/xbox_serie_x.jpg&#34; alt=&#34;Console Xbox Série X avec une manette&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://flickr.com/photos/144333438@N07/49626743158/&#34;&gt;profil de ru3ch initiative sur Flickr&lt;/a&gt;&lt;/em&gt; sous licence CC BY 2.0.&lt;/p&gt;
&lt;h2 id=&#34;avantages-1&#34;&gt;Avantage(s)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;console &lt;strong&gt;puissante&lt;/strong&gt;, ce qui permet d&amp;rsquo;accéder à des &lt;strong&gt;images plus fines&lt;/strong&gt; et proches de la réalité&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;esthétique&lt;/strong&gt; de la console, tout en prenant &lt;strong&gt;peu de place&lt;/strong&gt; ET &lt;strong&gt;passe inaperçue dans le salon&lt;/strong&gt; (vous ne passerez pas pour un gosse en soirée &amp;#x1f923;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tout repose sur l&amp;rsquo;abonnement au Game Pass&lt;/strong&gt; : accès illimité pour &lt;strong&gt;11€/mois&lt;/strong&gt; à une quantité incroyable de jeux. Vous trouverez toujours votre bonheur.&lt;/li&gt;
&lt;li&gt;accès dès le premier jour à des &lt;strong&gt;jeux dès leur sortie&lt;/strong&gt; (Halo, Starfield, Sea of thieves, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;inconvénients-1&#34;&gt;Inconvénient(s)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;le &lt;strong&gt;budget d&amp;rsquo;achat&lt;/strong&gt; initial est &lt;strong&gt;conséquent&lt;/strong&gt; (550€)&lt;/li&gt;
&lt;li&gt;jeux &lt;strong&gt;neufs très chers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;pour jouer &lt;strong&gt;en ligne : abonnement nécessaire&lt;/strong&gt; (7€/mois minimum)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;au-minimum-sans-jeux-1&#34;&gt;Au minimum (sans jeux)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;634€&lt;/strong&gt; (550€ HA + 84€ abonnement)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;84€&lt;/strong&gt; (84€ abonnement)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;au-minimum-avec-ha-de-jeux-1&#34;&gt;Au minimum (avec HA de jeux)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;1434€&lt;/strong&gt; (550€ HA + 84€ abonnement + 10 jeux neufs × 80€)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;884€&lt;/strong&gt; (84€ abonnement + 10 jeux neufs × 80€)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;au-maximum-abonnement-game-pass-console-à-11mois&#34;&gt;Au maximum (abonnement Game Pass Console à 11€/mois)&lt;/h2&gt;
&lt;p&gt;Avec l&amp;rsquo;achat d&amp;rsquo;un abonnement - complet - donnant accès à un catalogue de plus de 100 jeux vidéos, soit &lt;strong&gt;11€ × 12 mois = 132€&lt;/strong&gt;. Ceci enlève le besoin d&amp;rsquo;avoir 10 jeux neufs par an…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;682€&lt;/strong&gt; (550€ HA + 132€ abonnement Game Pass Console)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;132€&lt;/strong&gt; (132€ abonnement Game Pass Console)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion-intermédiaire---xbox-x&#34;&gt;Conclusion intermédiaire - Xbox X&lt;/h2&gt;
&lt;p&gt;Le catalogue de jeux vidéos du &lt;strong&gt;Game Pass Console (à 11€/mois)&lt;/strong&gt; donne non seulement accès à beaucoup de jeux vidéos, mais il permet en plus d&amp;rsquo;&lt;strong&gt;accéder à la plupart des sorties de jeux vidéos dès le premier jour&lt;/strong&gt; !&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est &lt;strong&gt;ce qui fait toute la force de cette console :&lt;/strong&gt; tant que &lt;strong&gt;le Game Pass Console&lt;/strong&gt; existe, l&amp;rsquo;accès à des jeux vidéos coûte 132€ par an - excepté toute modification du prix évidemment.&lt;/p&gt;
&lt;p&gt;Si vous consommez &lt;strong&gt;plus de 2 jeux par an, la Xbox Serie X sera très rentable dès les premières années&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;En revanche, je trouve que &lt;strong&gt;sans l&amp;rsquo;abonnement Game Pass Console&lt;/strong&gt; (11€/mois), &lt;strong&gt;la console est coûteuse&lt;/strong&gt;. Cela revient à acheter une brique de 550€ à poser dans le salon sans jamais y toucher, avec des jeux horriblement chers.&lt;/p&gt;
&lt;h1 id=&#34;sony-playstation-5-fat&#34;&gt;Sony Playstation 5 FAT&lt;/h1&gt;
&lt;h2 id=&#34;les-chiffres-2&#34;&gt;Les chiffres&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Prix d&amp;rsquo;&lt;strong&gt;achat&lt;/strong&gt; (sur Amazon) : &lt;strong&gt;~ 525€&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prix &lt;strong&gt;abonnement annuel&lt;/strong&gt; minimum : &lt;strong&gt;~ 72€&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Avantage abonnement : &lt;strong&gt;3 jeux par mois&lt;/strong&gt; (~ 36 jeux sur l&amp;rsquo;année)&lt;/li&gt;
&lt;li&gt;Abonnement familial : &lt;strong&gt;aucun&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Manettes disponibles à l&amp;rsquo;achat : &lt;strong&gt;1&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Particularité : &lt;strong&gt;très puissante pour les graphismes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prix d&amp;rsquo;un jeu neuf : &lt;strong&gt;~80€&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prix du même jeu en occasion : &lt;strong&gt;~40&lt;/strong&gt; (varie en fonction des régions et de l&amp;rsquo;interlocuteur + capacité à discuter le prix)&lt;/li&gt;
&lt;li&gt;Prix d&amp;rsquo;une manette : &lt;strong&gt;~ 70€&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;À noter : Le prix d&amp;rsquo;une Playstation 5 SLIM est quasi similaire (525€).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/materiel/sony_ps5.jpg&#34; alt=&#34;Console Playstation 5 Standard FAT&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;avantages-2&#34;&gt;Avantage(s)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;console &lt;strong&gt;puissante&lt;/strong&gt;, ce qui permet d’accéder à des &lt;strong&gt;images plus fines&lt;/strong&gt; et proches de la réalité&lt;/li&gt;
&lt;li&gt;la plupart des &lt;strong&gt;jeux PS4 fonctionnent&lt;/strong&gt; sur cette console avec une amélioration graphique&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rapidité de chargement&lt;/strong&gt; des niveaux, grâce à un disque dur SSD embarqué&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;inconvénients-2&#34;&gt;Inconvénient(s)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;le &lt;strong&gt;budget d&amp;rsquo;achat&lt;/strong&gt; initial est &lt;strong&gt;conséquent&lt;/strong&gt; (525€)&lt;/li&gt;
&lt;li&gt;jeux &lt;strong&gt;neufs très chers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;pour jouer &lt;strong&gt;en ligne : abonnement nécessaire&lt;/strong&gt; (6€/mois minimum)&lt;/li&gt;
&lt;li&gt;le &lt;a href=&#34;https://www.lesnumeriques.com/joypad/pourquoi-le-drift-de-la-manette-ps5-dualsense-n-est-pas-si-surprenant-n160739.html&#34;&gt;DualSense Drift de la manette de PS5&lt;/a&gt; qui &lt;strong&gt;réduit la durée de vie d&amp;rsquo;une manette à 417h&lt;/strong&gt;, soit environ &lt;strong&gt;7 mois d&amp;rsquo;utilisation&lt;/strong&gt; (à raison de 2h par jour) - sans possibilité de réparation pour le moment&lt;/li&gt;
&lt;li&gt;un &lt;a href=&#34;https://www.numerama.com/pop-culture/1232326-utiliser-sa-ps5-a-la-verticale-est-il-dangereux-pas-si-vite.html&#34;&gt;potentiel problème de liquide de refroidissment sur la PS5 ?&lt;/a&gt; sur une petite partie des consoles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;prend une place monstrueuse&lt;/strong&gt; au salon&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;au-minimum-sans-jeux-2&#34;&gt;Au minimum (sans jeux)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;597€&lt;/strong&gt; (525€ HA + 72€ abonnement)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;72€&lt;/strong&gt; (72€ abonnement)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;au-minimum-avec-ha-de-jeux-2&#34;&gt;Au minimum (avec HA de jeux)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;1397€&lt;/strong&gt; (525€ HA + 72€ abonnement + 10 jeux neufs × 80€)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;872€&lt;/strong&gt; (72€ abonnement + 10 jeux neufs × 80€)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;au-maximum-abonnement-premium-à-152an&#34;&gt;Au maximum (abonnement Premium à ~152€/an)&lt;/h2&gt;
&lt;p&gt;L&amp;rsquo;abonnement Premium donne accès à un bon catalogue de jeux vidéos. Cependant vous n&amp;rsquo;aurez pas accès aux sorties des jeux vidéos : il faudra patienter quelques années à chaque fois.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1&lt;sup&gt;ère&lt;/sup&gt; année : &lt;strong&gt;677€&lt;/strong&gt; (525€ HA + 152€ abonnement Premium)&lt;/li&gt;
&lt;li&gt;années suivantes : &lt;strong&gt;152€&lt;/strong&gt; (152€ abonnement Premium)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion-intermédiaire---ps5&#34;&gt;Conclusion intermédiaire - PS5&lt;/h2&gt;
&lt;p&gt;Se tourner vers cette console paraît curieux, à moins que vous n&amp;rsquo;&lt;strong&gt;êtes un grand fan de Playstation&lt;/strong&gt; - comme je l&amp;rsquo;ai été de la PS1 à la PS4 - et que vous appréciez à la fois la qualité d&amp;rsquo;image et des &lt;strong&gt;jeux en exclusivité&lt;/strong&gt; sur cette console.&lt;/p&gt;
&lt;p&gt;En effet, malgré la qualité des jeux vidéos (souvent à 1 seul joueur), ces jeux ont un &lt;strong&gt;prix élevé&lt;/strong&gt;. On se tournerait alors vers l&amp;rsquo;abonnement premium (152€/an) qui est « rentable » si vous consommez plus de 2 jeux par an.&lt;/p&gt;
&lt;p&gt;Cependant &lt;strong&gt;l&amp;rsquo;abonnement Premium ne permet pas d&amp;rsquo;accéder régulièrement à des nouveautés&lt;/strong&gt; (comprendre des jeux qui viennent de sortir), il y a une forme de patience à avoir.&lt;/p&gt;
&lt;p&gt;Si vous achetez 1 jeu neuf et l&amp;rsquo;abonnement pour jouer en ligne, cela vous revient au prix de l&amp;rsquo;abonnement Premium.&lt;/p&gt;
&lt;p&gt;Au final il &lt;strong&gt;bien trop d&amp;rsquo;inconvénients à cette console&lt;/strong&gt; pour si peu d&amp;rsquo;avantages comparé à la concurrence : que se passe-t-il chez Sony ? &amp;#x1f914;&lt;/p&gt;
&lt;h1 id=&#34;récapitulatif-des-chiffres&#34;&gt;Récapitulatif des chiffres&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;/th&gt;
          &lt;th&gt;Switch&lt;/th&gt;
          &lt;th&gt;Switch OLED&lt;/th&gt;
          &lt;th&gt;Switch Lite&lt;/th&gt;
          &lt;th&gt;Xbox S&lt;/th&gt;
          &lt;th&gt;Xbox X&lt;/th&gt;
          &lt;th&gt;PS5 FAT&lt;/th&gt;
          &lt;th&gt;PS5 Slim&lt;/th&gt;
          &lt;th&gt;PS5 Digital Slim&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Achat&lt;/td&gt;
          &lt;td&gt;250 €&lt;/td&gt;
          &lt;td&gt;300 €&lt;/td&gt;
          &lt;td&gt;200 €&lt;/td&gt;
          &lt;td&gt;300 €&lt;/td&gt;
          &lt;td&gt;550 €&lt;/td&gt;
          &lt;td&gt;525 €&lt;/td&gt;
          &lt;td&gt;550 €&lt;/td&gt;
          &lt;td&gt;450 €&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Abonnement&lt;/td&gt;
          &lt;td&gt;20 €&lt;/td&gt;
          &lt;td&gt;20 €&lt;/td&gt;
          &lt;td&gt;20 €&lt;/td&gt;
          &lt;td&gt;84 €&lt;/td&gt;
          &lt;td&gt;84 €&lt;/td&gt;
          &lt;td&gt;72 €&lt;/td&gt;
          &lt;td&gt;72 €&lt;/td&gt;
          &lt;td&gt;72 €&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Abo. Familial (switch)&lt;/td&gt;
          &lt;td&gt;35 €&lt;/td&gt;
          &lt;td&gt;35 €&lt;/td&gt;
          &lt;td&gt;35 €&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Game Pass Console (xbox)&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;132 €&lt;/td&gt;
          &lt;td&gt;132 €&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Abo. Premium (PS5)&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;Aucun&lt;/td&gt;
          &lt;td&gt;152 €&lt;/td&gt;
          &lt;td&gt;152 €&lt;/td&gt;
          &lt;td&gt;152 €&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Jeu neuf&lt;/td&gt;
          &lt;td&gt;50 €&lt;/td&gt;
          &lt;td&gt;50 €&lt;/td&gt;
          &lt;td&gt;50 €&lt;/td&gt;
          &lt;td&gt;80 €&lt;/td&gt;
          &lt;td&gt;80 €&lt;/td&gt;
          &lt;td&gt;80 €&lt;/td&gt;
          &lt;td&gt;80 €&lt;/td&gt;
          &lt;td&gt;80 €&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Jeu occasion&lt;/td&gt;
          &lt;td&gt;30 €&lt;/td&gt;
          &lt;td&gt;30 €&lt;/td&gt;
          &lt;td&gt;30 €&lt;/td&gt;
          &lt;td&gt;40 €&lt;/td&gt;
          &lt;td&gt;40 €&lt;/td&gt;
          &lt;td&gt;40 €&lt;/td&gt;
          &lt;td&gt;40 €&lt;/td&gt;
          &lt;td&gt;40 €&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Manette&lt;/td&gt;
          &lt;td&gt;45 €&lt;/td&gt;
          &lt;td&gt;45 €&lt;/td&gt;
          &lt;td&gt;45 €&lt;/td&gt;
          &lt;td&gt;60 €&lt;/td&gt;
          &lt;td&gt;60 €&lt;/td&gt;
          &lt;td&gt;70 €&lt;/td&gt;
          &lt;td&gt;70 €&lt;/td&gt;
          &lt;td&gt;70 €&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Totaux :&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;sup&gt;ère&lt;/sup&gt; année (&lt;strong&gt;HA + abo&lt;/strong&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;270 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;320 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;220 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;384 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;634 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;597 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;622 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;522 €&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Nbre jeux rentabilité (&lt;strong&gt;Abo&lt;/strong&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,4&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,4&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,4&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;1,05&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;1,05&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,9&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,9&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,9&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;sup&gt;ère&lt;/sup&gt; année (&lt;strong&gt;HA + abo. Prem/Fam/Console&lt;/strong&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;285 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;335 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;235 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;432 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;682 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;677 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;702 €&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;602 €&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Nbre jeux rentabilité (&lt;strong&gt;HA + abo. Prem/Fam/Console&lt;/strong&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,7&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,7&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,7&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;1,65&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;1,65&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;1,9&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;1,9&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;1,9&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Si budget de 700€ :&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Nbre jeux neufs rentabilité (&lt;strong&gt;Abo&lt;/strong&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;8,60&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;7,60&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;9,60&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;3,95&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,83&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;1,29&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,98&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;2,23&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Nbre jeux neufs rentabilité (&lt;strong&gt;Abo. Prem/Fam/Console&lt;/strong&gt;)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;8,30&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;7,30&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;9,30&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;3,35&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,23&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;0,29&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;-0,03&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;1,23&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;2 possibilités la première année :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;achat de la console et abonnement simple (&lt;strong&gt;HA + abo&lt;/strong&gt;),&lt;/li&gt;
&lt;li&gt;ou achat de la console avec l&amp;rsquo;abonnement « intéressant » : Premium pour PS5, Familial pour Switch et Game Pass Console pour Xbox (&lt;strong&gt;HA + abo. Prem/Fam/Console&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ensuite, pour chacune des possibilités nous calculons le &lt;strong&gt;nombre de jeux gratuits à consommer sur l&amp;rsquo;abonnement pour arriver à rentabilité&lt;/strong&gt; ; en comparaison au prix de jeux neufs donc. Le calcul est : prix de l&amp;rsquo;abonnement à l&amp;rsquo;année divisé par le prix d&amp;rsquo;un jeu neuf.&lt;/p&gt;
&lt;p&gt;Finalement les deux dernières lignes calculent le nombre de jeux neufs qu&amp;rsquo;on peut acheter ((700 - prix HA - abonnement choisi) ÷ prix jeu neuf) si on avait un budget initial de 700€. Et cela dans deux situations :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;avec un abonnement simple,&lt;/li&gt;
&lt;li&gt;avec un abonnement premium/familial/console tel qu&amp;rsquo;évoqué ci-avant.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Notez que si le chiffre est négatif alors il faudra ajouter un peu d&amp;rsquo;argent pour acheter un jeu.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Après avoir traité chaque console en étudiant son prix, les abonnements possibles, ce à quoi nous avons accès, les problèmes matériels éventuels et le prix des jeux neufs et d&amp;rsquo;occasion, je pense qu&amp;rsquo;on peut imaginer quelques types de public pour chacune des consoles.&lt;/p&gt;
&lt;p&gt;À mon sens les &lt;strong&gt;petits budgets&lt;/strong&gt; se tourneront vers la &lt;strong&gt;Nintendo Switch&lt;/strong&gt; pour 270€ (HA console + abonnement simple), ce qui permettra d&amp;rsquo;accéder à des jeux NES, SNES et GameBoyColor, le temps de regarder sur l&amp;rsquo;eShop (magasin virtuel) pour acheter des jeux à bas prix (soit à plus de 80% de réduction, soit pour petits budgets), il y a même des jeux gratuits comme des courses de voiture, des combats de Pokémon, etc. C&amp;rsquo;est une &lt;strong&gt;bonne entrée en matière&lt;/strong&gt; avec une souplesse « console de salon » vs. « portable ».&lt;/p&gt;
&lt;p&gt;Si, pour vous, &lt;strong&gt;la qualité d&amp;rsquo;image doit se rapprocher de la réalité dans les jeux vidéos&lt;/strong&gt;, sachez qu&amp;rsquo;&lt;strong&gt;on passe du simple au double avec la Xbox Serie X et la PS5 FAT&lt;/strong&gt; aux alentours de 500€. À ce prix là, il faut tout de même prendre un abonnement pour les jeux en ligne, pour une copie des sauvegardes des jeux, etc. Et là on douille : c&amp;rsquo;est plus de 70€ par an (soit quasiment le prix d&amp;rsquo;un jeu). Vu le prix des jeux sous ces consoles, il est clair que pour 132€/mois avec le Game Pass Console, c&amp;rsquo;est rentable en moins de 2 jeux par an ET avec un catalogue de plus de 100 jeux ET des nouveautés. C&amp;rsquo;est donc la &lt;strong&gt;Xbox Serie X avec abonnement Game Pass Console que vous devriez vous tourner&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Malheureusement la PS5&lt;/strong&gt;, avec ses problèmes de manettes, un abonnement qui ne donne accès qu&amp;rsquo;à peu de jeux, &lt;strong&gt;va être plus coûteuse sur le long terme&lt;/strong&gt;. Deux raisons pourraient justifier, selon moi, l&amp;rsquo;achat et l&amp;rsquo;utilisation de la console :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;accéder à des jeux en exclusivité sous PS5 (comme God of War, Horizon Forbidden West, Kena : bridge of spirit, Ratchet &amp;amp; Clank, etc.). Mais là encore &lt;strong&gt;les jeux deviennent disponibles sur PC&lt;/strong&gt; généralement (plateforme Steam par exemple)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;améliorer les performances de nos jeux PS4&lt;/strong&gt; et passer à une console plus moderne&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Au final &lt;strong&gt;je ne conseillerais que 2 consoles&lt;/strong&gt; (suivant les budgets) - alors que je suis pourtant un grand fan des consoles Sony :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la &lt;strong&gt;Nintendo Switch pour les petits budgets&lt;/strong&gt; et une &lt;strong&gt;utilisation plutôt familiale&lt;/strong&gt; (jeux à plusieurs, jeux « good vibes » simples, etc.), elle permet l&amp;rsquo;accès à des &lt;strong&gt;jeux rétros Nintendo&lt;/strong&gt; (NES, SNES, GameCube, Mega Drive, Nintendo 64, etc.),&lt;/li&gt;
&lt;li&gt;la &lt;strong&gt;Xbox Série X pour des budgets plus conséquents avec l&amp;rsquo;abonnement Game Pass Console&lt;/strong&gt; (11€/mois) pour accéder régulièrement à des nouveautés, des &lt;strong&gt;jeux variés et récents&lt;/strong&gt; et le plaisir des yeux niveau &lt;strong&gt;qualité d&amp;rsquo;image&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ma préférence, quitte à payer un abonnement mensuel, est d&amp;rsquo;utiliser le Game Pass Console sur la Xbox Série X pour pouvoir tester plusieurs jeux dès leur sortie. Et d&amp;rsquo;éventuellement acheter lesdits jeux en occasion dès que le prix me convient (pour les finir ou les garder à la maison).&lt;/p&gt;
&lt;p&gt;Sachez que, quoiqu&amp;rsquo;il arrive, dès que vous souhaitez jouer en ligne, &lt;strong&gt;la plupart des consoles vous amèneront à prendre un abonnement&lt;/strong&gt; minimal pour cela… Une console de jeu est finalement un budget à part entière de nos jours !&lt;/p&gt;
</description>
    </item>
    
    <item>
	    <title>Ordinateur portable Xiaomi Book Air 13 (version 2022)</title>
      <link>https://olivier.dossmann.net/2023/12/xiaomi-book-air-13-de-2022/</link>
      <pubDate>Fri, 01 Dec 2023 21:17:01 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2023/12/xiaomi-book-air-13-de-2022/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt; : article rédigé et publié ultérieurement (courant 2024). La date du 1er décembre représente approximativement l&amp;rsquo;arrivée de l&amp;rsquo;appareil dans le foyer.&lt;/p&gt;
&lt;h1 id=&#34;présentation&#34;&gt;Présentation&lt;/h1&gt;
&lt;p&gt;2024, &lt;strong&gt;écologiquement&lt;/strong&gt; parlant nous devrions &lt;strong&gt;faire durer un ordinateur un minimum de 5 à 7 ans&lt;/strong&gt; ! Mon dernier achat d&amp;rsquo;ordinateur portable était en décembre 2018, il y a exactement 5 ans ! C&amp;rsquo;était un &lt;a href=&#34;https://www.tuxboard.com/plan-notebook-air-13-3-pc-portable-economique-puissant/&#34;&gt;Xiaomi Mi Notebook Air 13.3 (version 2017)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Techniquement il fonctionne encore très bien. C&amp;rsquo;est pourquoi je l&amp;rsquo;ai donné à quelqu&amp;rsquo;un (en installant Windows 10 dessus, berk!). Je n&amp;rsquo;avais pas à en racheter un.&lt;/p&gt;
&lt;p&gt;Seulement voilà, les habitudes ont la vie rude ! Le confort de la mobilité (travail à l&amp;rsquo;extérieur, déplacements et utilisation dans différentes pièces de la maison) me manquait énormément.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est ainsi que mon côté technophile a eu raison de moi : j&amp;rsquo;ai fais l&amp;rsquo;acquisition d&amp;rsquo;un &lt;strong&gt;Xiaomi Book Air 13 (version 2022)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/materiel/Xiaomi-book-air-13.png&#34; alt=&#34;Apparence de l&amp;rsquo;ordinateur portable Xiaomi Book Air 13&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;description-du-produit&#34;&gt;Description du produit&lt;/h1&gt;
&lt;p&gt;Le Xiaomi Book Air 13 (version 2022) possède les caractéristiques suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un processeur &lt;strong&gt;Intel Core i5-1230U&lt;/strong&gt; (&lt;strong&gt;12e génération, 10 cœurs, 12 threads, jusqu&amp;rsquo;à 4.40Ghz&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;une mémoire vive de &lt;strong&gt;16 Go de RAM LPDDR5 cadencé à 5200 Mhz&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;un disque dur &lt;strong&gt;SSD de 512Go&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;une carte graphique intégrée &lt;strong&gt;Intel Iris Xe graphics&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;une batterie de &lt;strong&gt;12 heures d&amp;rsquo;utilisation&lt;/strong&gt; et 1 à 2h de charge&lt;/li&gt;
&lt;li&gt;un écran &lt;strong&gt;13 pouces 360° OLED tactile&lt;/strong&gt; avec une résolution 2.8K&lt;/li&gt;
&lt;li&gt;un &lt;strong&gt;lecteur d&amp;rsquo;empreinte&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bluetooth 5.2&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wifi 6E&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2 prises USB 3 de Type C Thunderbolt&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;une &lt;strong&gt;prise jack&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;poids de &lt;strong&gt;1,3 kg&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;épaisseur de &lt;strong&gt;12 mm&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il n&amp;rsquo;y a &lt;strong&gt;pas de ventilation ni d&amp;rsquo;aération&lt;/strong&gt; : vous n&amp;rsquo;entendrez jamais tourner cet ordinateur.&lt;/p&gt;
&lt;h1 id=&#34;mes-impressions&#34;&gt;Mes impressions&lt;/h1&gt;
&lt;p&gt;Cet ordinateur, en plus d&amp;rsquo;avoir de bonnes caractéristiques pour l&amp;rsquo;année 2022, ressemble à un &lt;strong&gt;véritable bijou&lt;/strong&gt; : il est brillant, présenté comme une parure qu&amp;rsquo;on mettrait sur soi.&lt;/p&gt;
&lt;p&gt;Il est &lt;strong&gt;pratique : très léger, très maniable&lt;/strong&gt; (se plie même en mode tablette, c&amp;rsquo;est dire !) et &lt;strong&gt;tient longtemps&lt;/strong&gt; (entre 10h et 12h d&amp;rsquo;autonomie). Il est très impressionnant.&lt;/p&gt;
&lt;p&gt;Cependant sans le stylo spécifique (non fourni par Xiaomi) de cet ordinateur, &lt;strong&gt;l&amp;rsquo;écran tactile n&amp;rsquo;est pas très utile&lt;/strong&gt;. Au contraire : il me pose problème régulièrement. Sans doute ne suis-je pas habitué aux écrans taciles. Par contre plier l&amp;rsquo;ordinateur et le &lt;strong&gt;poser comme un écran de TV&lt;/strong&gt; est pratique !&lt;/p&gt;
&lt;p&gt;Étant donné qu&amp;rsquo;il est &lt;strong&gt;silencieux&lt;/strong&gt;, car aucune ventilation, on pourrait s&amp;rsquo;attendre à ce qu&amp;rsquo;il chauffe énormément. Mais ce n&amp;rsquo;est pas le cas. Il chauffe, certes, mais avec l&amp;rsquo;assemblage aluminium tout autour cela passe très bien.&lt;/p&gt;
&lt;p&gt;Je regrette qu&amp;rsquo;il soit si fin et donc &lt;strong&gt;quasiment pas réparable&lt;/strong&gt; : si la moindre pièce venait à tomber en panne, il faudrait quasiment changer l&amp;rsquo;ordinateur portable entier. Cela m&amp;rsquo;embête un peu.&lt;/p&gt;
&lt;p&gt;On notera également un &lt;strong&gt;écran avec une définition et des couleurs à couper le souffle&lt;/strong&gt; ! Et surtout un peu compliqué à configurer pour moi sur ArchLinux car la résolution était tellement grande qu&amp;rsquo;il a fallu déterminer un ratio d&amp;rsquo;aggrandissement. J&amp;rsquo;ai ri - de honte &amp;#x1f609;.&lt;/p&gt;
&lt;p&gt;A contrario je déplore le manque d&amp;rsquo;informations pour savoir comment faire fonctionner la Webcam sur GNU/Linux pour cette machine. Impossible pour le moment &amp;#x1f937;.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Je dois dire que cet ordinateur est un &lt;strong&gt;objet de très bonne facture&lt;/strong&gt;. Avec du matériel à la hauteur, de &lt;strong&gt;bonnes caractéristiques techniques, léger, pratique et silencieux&lt;/strong&gt;. Et pas cher pour ce que c&amp;rsquo;est !&lt;/p&gt;
&lt;p&gt;Pourtant le côté &lt;strong&gt;peu réparable&lt;/strong&gt;, un écran tactile - presque - inutile et une &lt;strong&gt;webcam ne fonctionnant pas sous GNU/Linux&lt;/strong&gt;, m&amp;rsquo;ont légèrement irrité.&lt;/p&gt;
&lt;p&gt;Je pense ne pas garder cet ordinateur portable longtemps et le revendre dès que j&amp;rsquo;aurais trouvé un ordinateur qui me seille bien plus.&lt;/p&gt;
</description>
    </item>
    
    <item>
	    <title>La Genèse d&#39;un projet</title>
      <link>https://olivier.dossmann.net/2023/09/la-gen%C3%A8se-dun-projet/</link>
      <pubDate>Wed, 13 Sep 2023 12:13:23 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2023/09/la-gen%C3%A8se-dun-projet/</guid>
      <description>&lt;p&gt;Il y a quelques temps je lançais un billet sur &lt;a href=&#34;https://olivier.dossmann.net/2023/01/la-gachette-qui-publie-mon-blog/&#34;&gt;le projet Gachette&lt;/a&gt; qui permet de publier mon blog. Dans la même lancée &lt;strong&gt;je souhaite aujourd&amp;rsquo;hui vous présenter un autre projet&lt;/strong&gt; sur lequel je travaille de temps en temps : &lt;strong&gt;&lt;a href=&#34;https://github.com/blankoworld/genese&#34;&gt;Genèse&lt;/a&gt;&lt;/strong&gt;. Genèse est assez difficile à définir. Cependant je l&amp;rsquo;imagine comme une &lt;strong&gt;commande unique pour permettre à plusieurs développeurs de travailler sur un environnement commun&lt;/strong&gt; et en lançant &lt;strong&gt;une instance par&lt;/strong&gt; &lt;em&gt;ticket&lt;/em&gt;/problème relevé.&lt;/p&gt;
&lt;p&gt;Cet outil, bien qu&amp;rsquo;il soit &lt;strong&gt;utile et facile à utiliser&lt;/strong&gt;, demande un minimum d&amp;rsquo;explication pour comprendre à la fois le concept et l&amp;rsquo;utilité réelle.&lt;br /&gt;
C&amp;rsquo;est pourquoi je vais avant tout poser la problématique principale qui a initiée le projet, puis montrer quelques usages intéressants qui sont plus parlants et finalement tenter d&amp;rsquo;expliquer son fonctionnement en interne.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/lieux/genesis.jpg&#34; alt=&#34;Explosion d&amp;rsquo;artifice au dessus de l&amp;rsquo;eau&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://flickr.com/photos/23024164@N06/&#34;&gt;profil de Damian Gadal sur Flickr&lt;/a&gt;&lt;/em&gt; sous licence CC BY 2.0.&lt;/p&gt;
&lt;h1 id=&#34;ce-qui-a-initié-le-projet&#34;&gt;Ce qui a initié le projet&lt;/h1&gt;
&lt;p&gt;De &lt;a href=&#34;https://olivier.dossmann.net/cv/&#34;&gt;nombreuses années d&amp;rsquo;expérience professionnelle dans le domaine informatique&lt;/a&gt; m&amp;rsquo;ont amené à rencontrer plusieurs problèmes et à réfléchir sur énormément de sujets.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;un d&amp;rsquo;eux se porte sur l&amp;rsquo;environnement de travail : je parle de l&amp;rsquo;environnement système utilisé pour travailler sur un projet. J&amp;rsquo;ai relevé quelques éléments intéressants, similaires à des postulats :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on essaie souvent de se rapprocher de l&amp;rsquo;environnement système de la production : ceci pour repérer assez tôt d&amp;rsquo;éventuels problèmes&lt;/li&gt;
&lt;li&gt;plus l&amp;rsquo;environnement entre collègues est similaire, mieux nous travaillons : si un collaborateur rencontre un problème il peut se tourner vers le reste de l&amp;rsquo;équipe pour avoir de l&amp;rsquo;aide&lt;/li&gt;
&lt;li&gt;nous en arrivons souvent à faire un fichier docker-compose.yml pour cela : peut-être est-ce initialement plus facile de partager un fichier léger (docker-compose.yml) qu&amp;rsquo;une machine virtuelle entière ?&lt;/li&gt;
&lt;li&gt;quand on nouveau collaborateur arrive dans l&amp;rsquo;équipe, il a pas mal de choses à apprendre sur le projet. Et il peine souvent - en plus de toutes les choses à apprendre - à devoir installer l&amp;rsquo;environnement initial&lt;/li&gt;
&lt;li&gt;on utilise souvent un fichier docker-compose.yml très proche entre plusieurs projets : ce qui est normal puisqu&amp;rsquo;on utilise très souvent des technologies similaires qu&amp;rsquo;on maîtrise pour les vendre à nos clients&lt;/li&gt;
&lt;li&gt;on travaille souvent sur plusieurs &lt;em&gt;tickets&lt;/em&gt;, c&amp;rsquo;est à dire plusieurs problèmes émis par le client. Chaque fois que nous démarrons un nouveau ticket, dans l&amp;rsquo;idéal, nous devrions avoir un environnement sain et propre pour ne pas avoir de fioritures de nos travaux précédents&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En discutant avec &lt;a href=&#34;https://www.richard-dern.fr/&#34;&gt;Richard Dern&lt;/a&gt; (qui a d&amp;rsquo;ailleurs &lt;a href=&#34;https://www.richard-dern.fr/blog/2023/09/03/nouveau-site-en-ligne/&#34;&gt;fait une refonte de son site web avec un nouveau moteur de blog&lt;/a&gt;), nous avons réfléchi à un outil capable de résoudre plusieurs de ces problématiques. Le fil rouge était :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les environnements doivent &lt;strong&gt;rester isolés&lt;/strong&gt; : utilisation d&amp;rsquo;un fichier docker-compose.yml pour générer un environnement&lt;/li&gt;
&lt;li&gt;création d&amp;rsquo;un &lt;strong&gt;répertoire unique pour chaque nouveau ticket/projet/autre&lt;/strong&gt; afin de garder quelque chose de sain et propre&lt;/li&gt;
&lt;li&gt;éviter de devoir se répéter entre plusieurs projets : &lt;strong&gt;mettre en commun&lt;/strong&gt; les éléments qui le peuvent, comme par exemple le type de base de données&lt;/li&gt;
&lt;li&gt;permettre à &lt;strong&gt;plusieurs utilisateurs de travailler sur la même machine&lt;/strong&gt; : nommage des environnements d&amp;rsquo;une manière particulière (avec le nom de l&amp;rsquo;utilisateur par exemple)&lt;/li&gt;
&lt;li&gt;permettre à chaque développeur de &lt;strong&gt;personnaliser son environnement&lt;/strong&gt; : par exemple s&amp;rsquo;il souhaite avoir une interface web pour la base de données, qu&amp;rsquo;il puisse rajouter l&amp;rsquo;outil qu&amp;rsquo;il souhaite&lt;/li&gt;
&lt;li&gt;si nous travaillons sur 2 tickets d&amp;rsquo;un même projet, sachant que l&amp;rsquo;environnement est similaire pour un même projet, ces deux environnements doivent pouvoir exister en même temps : s&amp;rsquo;ils utilisent les mêmes ports d&amp;rsquo;adresses, cela va échouer. Il faut donc des &lt;strong&gt;ports aléatoires&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;si les ports sont aléatoires, alors il faut un accès facile à chacun des environnements, par exemple à l&amp;rsquo;aide d&amp;rsquo;une &lt;strong&gt;interface Web commune&lt;/strong&gt; à tous ces environnements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C&amp;rsquo;est assez difficile à se l&amp;rsquo;imaginer sans des explications, une démonstration et/ou quelqu&amp;rsquo;un qui nous guide pour nous montrer le fonctionnement, alors je vais vous présenter un cas d&amp;rsquo;usage.&lt;/p&gt;
&lt;h1 id=&#34;usage-et-exemple-de-genèse&#34;&gt;Usage et exemple de Genèse&lt;/h1&gt;
&lt;p&gt;Imaginons un cas d&amp;rsquo;usage typique : un client détient une application web (faite avec un &lt;a href=&#34;https://fr.m.wikipedia.org/wiki/Framework&#34;&gt;framework&lt;/a&gt;) qui utilise une base de données MySQL. Appelons cette application : memory_game.&lt;/p&gt;
&lt;p&gt;Il est très probable que nous ayons d&amp;rsquo;autres clients qui utilisent MySQL. Et il est très probable que notre client fera des tickets de bugs que nous aurons à résoudre. Nous aurons probablement plusieurs collaborateurs (pour lesquels nous allons répartir les tickets).&lt;/p&gt;
&lt;p&gt;Il utilise un fichier docker-compose.yml avec le contenu suivant :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;php&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;toasterlint/php-apache-mysql&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;8888:80&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;./:/var/www/html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;db&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;mysql&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;command&lt;/span&gt;: --&lt;span style=&#34;color:#ae81ff&#34;&gt;default-authentication-plugin=mysql_native_password&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;mot2passe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;MYSQL_DATABASE&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;maBdd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;./base_de_donnees:/docker-entrypoint-initdb.d&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On comprend donc qu&amp;rsquo;il y a :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un service (nommé db) pour une base de données MySQL,&lt;/li&gt;
&lt;li&gt;un service (nommé php) pour l&amp;rsquo;application écrite en PHP sur le port 8888.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Avec Genèse&lt;/strong&gt;, générer un nouvel environnement de développement reviendrait à faire :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Génère un docker-compose.yml dans le dossier instances/memory_game à partir du profil nommé memory_game&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./genese -p memory_game
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;instances/memory_game est un répertoire de travail&lt;/strong&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;avec le dépôt de version du projet memory_game,&lt;/li&gt;
&lt;li&gt;un fichier docker-compose.yml prévu pour lancer un environnement complet,&lt;/li&gt;
&lt;li&gt;et un fichier &lt;strong&gt;.env&lt;/strong&gt; contenant des variables permettant au projet d&amp;rsquo;être autonome.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si l&amp;rsquo;exécutable &lt;em&gt;./genese&lt;/em&gt; venait à disparaître, le dossier reste fonctionnel pour travailler (avec Docker Compose évidemment).&lt;/p&gt;
&lt;p&gt;Si on travaille sur plusieurs problèmes en parallèle, on peut vouloir créer un dossier par problème. Imaginons le &lt;strong&gt;ticket 42&lt;/strong&gt; et le &lt;strong&gt;ticket 16&lt;/strong&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Génère une instance du projet dans le dossier instances/ticket42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./genese -p memory_game -n ticket42
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Même chose avec le dossier instances/ticket16&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./genese -p memory_game -n ticket16
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il faut récupérer une branche spéciale du service memory_game ?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Récupère dans le dépôt Git fourni dans le service memory_game la branche maBrancheSpeciale&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BRANCHE_MEMORY_GAME&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;maBrancheSpeciale&amp;#34;&lt;/span&gt; ./genese -p memory_game -n essaiautrebranche
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vous découvrirez dans un prochain article à quel usage je réserve cela &amp;#x1f609;&lt;/p&gt;
&lt;p&gt;Quelles sont les instances dont je dispose ?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Liste l&amp;#39;ensemble des instances&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./genese -i
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et j&amp;rsquo;obtiens une liste des dossiers ayant été créés.&lt;/p&gt;
&lt;p&gt;Si je veux supprimer une instance spécifique :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Supprimer l&amp;#39;instance ticket16&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./genese -s ticket16
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et si on veut avoir une visualisation des instances lancées, d&amp;rsquo;accéder à leur détail, éteindre un conteneur, le rallumer, regarder les fichiers de journalisation (logs) ou encore entrer dans un conteneur avec une invite de commande, on peut &lt;strong&gt;utiliser l&amp;rsquo;interface Web Portainer&lt;/strong&gt; fournie avec Genèse. Cela ressemble à quelque chose comme :&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/screenshots/portainer.png&#34; alt=&#34;Impression écran d&amp;rsquo;une liste d&amp;rsquo;instances lancées sur la machine locale&#34;&gt;&lt;/p&gt;
&lt;p&gt;Seriez-vous curieux de savoir comment cela fonctionne (sans entrer dans le technique évidemment !) ?&lt;/p&gt;
&lt;h1 id=&#34;comment-ça-marche-&#34;&gt;Comment ça marche ?&lt;/h1&gt;
&lt;p&gt;Nous allons voir que Genèse s&amp;rsquo;appuie sur quelques éléments clés comme :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;l&amp;rsquo;instance : version autonome et isolée, située dans le dossier &lt;strong&gt;instance&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;le service : la description nécessaire pour générer un service, par exemple MySQL,&lt;/li&gt;
&lt;li&gt;le profil : contient une liste de services permettant de démarrer une instance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Prenons l&amp;rsquo;exemple précédent, nous aurons :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;deux services :
&lt;ul&gt;
&lt;li&gt;l&amp;rsquo;un nommé &lt;code&gt;mysql&lt;/code&gt; pour la base de données,&lt;/li&gt;
&lt;li&gt;l&amp;rsquo;autre nommé &lt;code&gt;memory_game&lt;/code&gt; pour notre application,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;un profil nommé &lt;code&gt;memory_game&lt;/code&gt; qui liste les services &lt;code&gt;mysql&lt;/code&gt; et &lt;code&gt;memory_game&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Chaque fois que nous lancerons la commande &lt;code&gt;./genese&lt;/code&gt; avec le profil &lt;code&gt;memory_game&lt;/code&gt; nous aurons la possibilité de générer une instance avec un nom spécifique.&lt;/p&gt;
&lt;p&gt;Comment cela peut-il fonctionner ? Les services ont une structure permettant de décrire :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la &lt;strong&gt;partie du fichier docker-compose.yml&lt;/strong&gt; qui va être utilisée,&lt;/li&gt;
&lt;li&gt;la possibilité de donner le &lt;strong&gt;dépôt Git utilisé&lt;/strong&gt; pour récupérer les sources du projet et la &lt;strong&gt;branche par défaut&lt;/strong&gt; à récupérer,&lt;/li&gt;
&lt;li&gt;la possibilité de donner un dossier &lt;code&gt;extras&lt;/code&gt; permettant de &lt;strong&gt;surcharger les sources du projet récupéré&lt;/strong&gt; (par exemple pour mettre des fichiers de configuration),&lt;/li&gt;
&lt;li&gt;la possibilité d&amp;rsquo;&lt;strong&gt;agir à des moments clés de la génération de l&amp;rsquo;instance via des déclencheurs&lt;/strong&gt; qui sont des scripts pour :
&lt;ul&gt;
&lt;li&gt;procéder à des changements &lt;strong&gt;AVANT&lt;/strong&gt; le &lt;strong&gt;lancement des conteneurs Docker&lt;/strong&gt;, par exemple modifier des fichiers de configuration,&lt;/li&gt;
&lt;li&gt;agir &lt;strong&gt;APRÈS le lancement des conteneurs&lt;/strong&gt;, par exemple pour lancer des commandes dans les conteneurs Docker lancés,&lt;/li&gt;
&lt;li&gt;afficher des informations &lt;strong&gt;à la fin du processus de création de l&amp;rsquo;instance&lt;/strong&gt;, par exemple pour afficher les ports utilisés par les différents conteneurs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;À cela s&amp;rsquo;ajoute &lt;strong&gt;une interface Web&lt;/strong&gt; (&lt;a href=&#34;https://www.portainer.io/&#34; title=&#34;Interface Web de contrôle des instances Docker lancées&#34;&gt;Portainer&lt;/a&gt;) permettant de contrôler les instances lancées et accéder à des fonctionnalités particulières de Docker.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/blankoworld/genese#readme&#34;&gt;La documentation de Genèse&lt;/a&gt; devrait se charger bien mieux que moi pour les détails techniques et les possibilités de cet outil.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Malgré l&amp;rsquo;exemple d&amp;rsquo;utilisation et quelques détails sur son fonctionnement, Genèse mérite qu&amp;rsquo;on s&amp;rsquo;y attarde : nous n&amp;rsquo;avons gratté que la surface.&lt;/p&gt;
&lt;p&gt;Cela ressemble à un framework pour des profils de personnes de type &lt;a href=&#34;https://fr.wikipedia.org/wiki/Devops&#34;&gt;devops&lt;/a&gt; afin de leur fournir un outil unique ; à la fois déployer des instances pour les développeurs ; et des instances de type test pour les personnes fonctionnelles.&lt;/p&gt;
&lt;p&gt;Je ne sais pas comment suggérer de passer un peu de temps sur l&amp;rsquo;outil pour comprendre que c&amp;rsquo;est un bon investissement de temps. Surtout pour des personnes d&amp;rsquo;un profil DevOps et qui connaissent le scripting Bash. J&amp;rsquo;espère que la curiosité vous piquera au vif !&lt;/p&gt;
&lt;p&gt;Nous nous retrouverons très probablement pour en reparler dans un cadre différent encore.&lt;/p&gt;
</description>
    </item>
    
    <item>
	    <title>Bye Bye Gandi Mail, Bonjour Mailo</title>
      <link>https://olivier.dossmann.net/2023/08/bye-bye-gandi-mail-bonjour-mailo/</link>
      <pubDate>Fri, 25 Aug 2023 21:26:05 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2023/08/bye-bye-gandi-mail-bonjour-mailo/</guid>
      <description>&lt;p&gt;Ça fait &lt;a href=&#34;https://sebsauvage.net/links/?o9qvaA&#34;&gt;quelques mois qu&amp;rsquo;on nous rabache que Gandi Mail va devenir payant&lt;/a&gt;. &lt;a href=&#34;https://www.nextinpact.com/article/71947/gandi-passe-mails-en-payant-utilisateurs-cherchent-solutions-remplacement&#34;&gt;NextInpact affirme aussi que Gandi passe les mails en payant&lt;/a&gt;. Quel problème cela pose ? Où en suis-je ? Y a-t-il d&amp;rsquo;autres alternatives à cela ?&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/objets/boites_aux_lettres.jpg&#34; alt=&#34;Trois boîtes aux lettres en forme de maison&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://flickr.com/photos/irio/&#34;&gt;profil d&amp;rsquo;irio sur Flickr&lt;/a&gt;&lt;/em&gt; sous licence BY 2.0.&lt;/p&gt;
&lt;h1 id=&#34;problèmes-posés&#34;&gt;Problèmes posés&lt;/h1&gt;
&lt;p&gt;Gandi annonce la mise du service Gandi Mail payant à partir de fin septembre/début octobre. Le prix des boîtes mail passe &lt;strong&gt;de gratuit à 4.79€ par mois&lt;/strong&gt;. C&amp;rsquo;est à dire &lt;strong&gt;57.48€/an&lt;/strong&gt;. Et cela &lt;strong&gt;pour chaque boîte courriel !&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Le souci ? Quand on utilise plusieurs boîtes courriel, ça douille tout de suite plus ! Exemple : j&amp;rsquo;ai 4 boîtes courriel utilisées chez Gandi, &lt;strong&gt;ce qui me ferait passer de 0€/an à… 229.92€&lt;/strong&gt; !!&lt;/p&gt;
&lt;p&gt;Avouez que &lt;strong&gt;la facture est plutôt corsée&lt;/strong&gt; quand on a été habitué plus de 10 ans à ne rien débourser pour cela. Et encore, j&amp;rsquo;abuse un peu car il faut savoir que les domaines sous Gandi sont généralement plus chers que d&amp;rsquo;autres fournisseurs de domaines. Les adresses courriel gratuites et de bonne qualité amenait des clients chez Gandi.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;utilise Gandi pour l&amp;rsquo;ensemble de mes domaines car j&amp;rsquo;apprécie le service, les possibilités (comme le « Live DNS ») et - antérieurement - la possibilité de créer des adresses courriels avec 1 000 alias de redirection courriels (vous choisissez des adresses courriels qui vont rediriger vers 1 à plusieurs adresses courriels, même si les adresses cibles ne vous appartiennent pas).&lt;/p&gt;
&lt;p&gt;Et dans tout cela, où me situe-je ?&lt;/p&gt;
&lt;h1 id=&#34;où-jen-suis&#34;&gt;Où j&amp;rsquo;en suis&lt;/h1&gt;
&lt;p&gt;Si j&amp;rsquo;écris cet article, c&amp;rsquo;est parce que &lt;strong&gt;j&amp;rsquo;aimerais partager à la fois le fait qu&amp;rsquo;il y a du changement chez Gandi Mail, mais aussi mes pérégrinations en matière de recherche d&amp;rsquo;un fournisseur de mail&lt;/strong&gt; prenant en compte les noms de domaine sans forcément les gérer.&lt;/p&gt;
&lt;p&gt;On le dit souvent, en informatique il est intéressant de pouvoir changer un service sans avoir d&amp;rsquo;impact sur un autre : choisir un fournisseur d&amp;rsquo;adresses courriels sans changer de fournisseur de domaine par exemple. Et c&amp;rsquo;est ce que je visais.&lt;/p&gt;
&lt;h1 id=&#34;quelles-alternatives-&#34;&gt;Quelles alternatives ?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://sebsauvage.net/links/?o9qvaA&#34;&gt;Si SebSauvage propose Infomaniak&lt;/a&gt; en migrant ses domaines là bas, d&amp;rsquo;&lt;a href=&#34;https://ludovic.hirlimann.net/2023/06/gandi-je-suis-enerve-la-partie-email.html&#34;&gt;autres proposent différents services comme FastMail, Ikoula&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;La plupart du temps, il faut migrer ses domaines avec : ce que je ne recherche pas du tout. C&amp;rsquo;est le cas pour &lt;a href=&#34;https://www.ovhcloud.com/fr/&#34;&gt;OVH&lt;/a&gt; qui propose des offres quand on gère les domaines chez eux.&lt;/p&gt;
&lt;p&gt;Je suis alors tombé sur &lt;a href=&#34;https://jtremesay.org/migration-de-gandi-mail-vers-mailo.html&#34;&gt;un article intéressant sur le passage à Mailo.com&lt;/a&gt;, service que je ne connaissais pas. &lt;a href=&#34;https://www.mailo.com/&#34;&gt;Mailo.com&lt;/a&gt; est Français, garantit aux utilisateurs d&amp;rsquo;être respectueux de leurs données, ne pas les vendre à des tiers et visant une utilisation éthique et responsable du Web. Le service &lt;strong&gt;Mailo est gratuit, mais une option à 2€/mois existe&lt;/strong&gt;, ce qui permet de gérer 5 adresses mails. Ça tombe bien, j&amp;rsquo;ai 4 adresses à créer !&lt;/p&gt;
&lt;h1 id=&#34;quelques-détails-sur-ma-migration&#34;&gt;Quelques détails sur ma migration&lt;/h1&gt;
&lt;p&gt;Ce qui est intéressant dans ce dernier article sur Mailo.com, c&amp;rsquo;est que l&amp;rsquo;auteur suggère &lt;strong&gt;l&amp;rsquo;utilisation d&amp;rsquo;imapsync&lt;/strong&gt; comme outil pour synchroniser son ancienne boîte aux lettres avec la nouvelle. Et il donne les détails sur comment configurer tout cela.&lt;/p&gt;
&lt;p&gt;À noter une petite subtilité que je n&amp;rsquo;avais pas prise en compte : si sous Gandi Mail vous avez droit à 1 000 redirections courriel, sous Mailo c&amp;rsquo;est limité à 100 redirection par boîte courriel. Quand on a 390+ redirections… il faut faire du tri ! Fort heuresement, Mailo propose un fonctionnement intéressant : ajouter &lt;code&gt;++&lt;/code&gt; dans l&amp;rsquo;adresse courriel. Par exemple si vous faites une boîte &lt;a href=&#34;mailto:prenom.nom@domaine.tld&#34;&gt;prenom.nom@domaine.tld&lt;/a&gt;, vous pouvez créer dynamiquement &lt;a href=&#34;mailto:prenom.nom++quelquechose@domaine.tld&#34;&gt;prenom.nom++quelquechose@domaine.tld&lt;/a&gt;. Autant que vous voulez. Sans utiliser d&amp;rsquo;ordinateur. À la volée je vous disais !&lt;/p&gt;
&lt;p&gt;Autre chose à viser aussi : le catch-all. C&amp;rsquo;est le fait que n&amp;rsquo;importe quelle adresse mal écrite, ou différente de votre boîte courriel entraînera quand même la redirection vers votre boîte courriel. Exemple : au lieu d&amp;rsquo;écrire &lt;a href=&#34;mailto:prenom.nom@domaine.tld&#34;&gt;prenom.nom@domaine.tld&lt;/a&gt;, si je me trompe en écrivant &lt;a href=&#34;mailto:prenmo.nmo@domaine.tld&#34;&gt;prenmo.nmo@domaine.tld&lt;/a&gt;, je recevrais quand même l&amp;rsquo;adresse courriel.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Je joue les montagnes russes avec les prix : je suis passé de 4 boîtes Gandi Mail gratuites à potentiellement 230€/an pour finalement payer 24€/an. Le coût numérique augmente légèrement. Je pense être en droit de me demander jusqu&amp;rsquo;où cela ira pour bénéficier d&amp;rsquo;un pseudo contrôle de mes données et le choix de mes fournisseurs sur Internet ?&lt;/p&gt;
&lt;p&gt;Quoiqu&amp;rsquo;il en soit le passage de Gandi Mail à Mailo, même si rocambolesque et pas de tout repos, a été plus serein avec l&amp;rsquo;aide de l&amp;rsquo;&lt;a href=&#34;https://jtremesay.org/migration-de-gandi-mail-vers-mailo.html&#34;&gt;article de Jonathan Tremesaygues sur le passage de Gandi Mail à Mailo à l&amp;rsquo;aide d&amp;rsquo;imapsync&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Je trie encore mes 390+ redirections Gandi Mail vers Mailo au fur et à mesure, mais c&amp;rsquo;était nécessaire et je suis bien content de l&amp;rsquo;avoir fait, malgré le côté payant de la chose !&lt;/p&gt;
&lt;h1 id=&#34;liens-utiles&#34;&gt;Liens utiles&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.infomaniak.com/fr&#34;&gt;Infomaniak&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.fastmail.com/&#34;&gt;FastMail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ikoula.com/fr/&#34;&gt;Ikoula&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ovhcloud.com/fr/&#34;&gt;OVH&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.mailo.com/&#34;&gt;Mailo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://jtremesay.org/migration-de-gandi-mail-vers-mailo.html&#34;&gt;Article de Jonathan Tremesaygues sur le passage de Gandi Mail à Mailo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
	    <title>La Gachette qui publie mon blog</title>
      <link>https://olivier.dossmann.net/2023/01/la-gachette-qui-publie-mon-blog/</link>
      <pubDate>Fri, 20 Jan 2023 17:46:32 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2023/01/la-gachette-qui-publie-mon-blog/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Peut-être serez-vous surpris d&amp;rsquo;apprendre que la publication d&amp;rsquo;un article sur ce blog revient simplement à écrire du texte dans un fichier et &lt;a href=&#34;https://fr.wikipedia.org/wiki/Commit&#34;&gt;envoyer un commit&lt;/a&gt; sur un dépôt Git. &lt;strong&gt;Ni plus, ni moins&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est là que commence toute une &lt;strong&gt;chaîne de publication&lt;/strong&gt; afin de mettre à disposition le fameux article sur le Web ! Pour cela j&amp;rsquo;ai utilisé très peu d&amp;rsquo;outils et un peu d&amp;rsquo;imagination.&lt;/p&gt;
&lt;p&gt;Le but du présent article est de &lt;strong&gt;vous présenter l&amp;rsquo;outil de la chaîne que j&amp;rsquo;ai dû développer pour mener à bien ce projet : &lt;a href=&#34;https://github.com/blankoworld/gachette&#34;&gt;Gachette&lt;/a&gt;&lt;/strong&gt;. Puis de vous décrire comment le mettre en place.&lt;/p&gt;
&lt;p&gt;Mais avant tout commençons à planter le décor !&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/nature/goutte.jpg&#34; alt=&#34;Phénomène de goutte qui remonte après être tombé dans l&amp;rsquo;eau&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://flickr.com/photos/nikkvalentine/&#34;&gt;profil de Nikk sur Flickr&lt;/a&gt;&lt;/em&gt; sous licence CC BY 2.0.&lt;/p&gt;
&lt;h1 id=&#34;plantons-le-décor-avec-lhistoire-logicielle-de-ce-blog&#34;&gt;Plantons le décor avec l&amp;rsquo;Histoire logicielle de ce blog&lt;/h1&gt;
&lt;p&gt;(je comprendrais que ce chapitre ne soit pas très enthousiasmant pour vous, si c&amp;rsquo;est le cas, passez au suivant &amp;#x1f609;)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://olivier.dossmann.net/2016/03/hugo_le_moteur_de_blog_statique_rapide_et_moderne/&#34;&gt;En 2016 je vous parlais d&amp;rsquo;Hugo, le moteur de blog statique&lt;/a&gt; que j&amp;rsquo;utilise pour « confectionner » ce blog. Outil très intéressant qui &lt;strong&gt;utilise de simples fichiers pour générer un site web entier&lt;/strong&gt;, statique ; c&amp;rsquo;est à dire en pur HTML et ne demandant aucune autre ressource finale qu&amp;rsquo;un serveur Web tel qu&amp;rsquo;Apache2, nginx, lighttpd, Caddy Server et j&amp;rsquo;en passe… Dans ma situation, le serveur Web en question est Nginx depuis 2013 environ - mais qu&amp;rsquo;importe.&lt;/p&gt;
&lt;p&gt;Afin de garder en mémoire les travaux effectués, &lt;a href=&#34;https://olivier.dossmann.net/2017/04/gitea-service-git-sans-prise-de-t%C3%AAte-issu-de-gogs/&#34;&gt;je vous partageais en 2017 l&amp;rsquo;outil Gitea, service Git sans prise de tête issu de Gogs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;À cette époque (entre 2016 et 2019/2020), pour publier mon blog il me faut :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(manuel) écrire l&amp;rsquo;article dans &lt;strong&gt;un fichier texte&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;(manuel) (facultatif) l&amp;rsquo;enregistrer sous Git avec &lt;strong&gt;un commit&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;(manuel) (facultatif) &lt;strong&gt;envoyer&lt;/strong&gt; l&amp;rsquo;article &lt;strong&gt;sur Gitea&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;(manuel) &lt;strong&gt;compiler le site&lt;/strong&gt; à l&amp;rsquo;aide de la commande &lt;code&gt;hugo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;(manuel) &lt;strong&gt;synchroniser les fichiers résultants&lt;/strong&gt; sur mon serveur doté de Nginx, par exemple avec une commande &lt;code&gt;rsync&lt;/code&gt; simple&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;À force de &lt;a href=&#34;https://olivier.dossmann.net/2016/02/fosdem-2016/&#34;&gt;traîner à FOSDEM en 2016&lt;/a&gt; et &lt;a href=&#34;https://olivier.dossmann.net/2017/02/fosdem-2017-rencontre-avec-des-aliens/&#34;&gt;en 2017&lt;/a&gt;, j&amp;rsquo;ai non seulement appris que l&amp;rsquo;informatique sert à automatiser des tâches mais qu&amp;rsquo;il est aussi possible de le faire de manière « simple ».&lt;/p&gt;
&lt;p&gt;Je me renseigne et j&amp;rsquo;apprends que sous Gitlab, Github et Gitea (plateformes que j&amp;rsquo;utilise à l&amp;rsquo;époque), il existe un &lt;a href=&#34;https://blog.hubspot.fr/website/webhook&#34;&gt;système de webhooks&lt;/a&gt;. Qu&amp;rsquo;est-ce à dire ? Grossomodo je peux configurer ces plateformes pour qu&amp;rsquo;à &lt;strong&gt;chaque envoi de mon travail peut résulter un appel à une adresse Web&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Il suffit ensuite, à l&amp;rsquo;adresse appelée, de &lt;strong&gt;pouvoir étudier la requête envoyée et d&amp;rsquo;agir en conséquence&lt;/strong&gt; (par exemple déployer un site).&lt;/p&gt;
&lt;p&gt;Sur le papier ça a l&amp;rsquo;air fun :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(manuel) j&amp;rsquo;écris mon article dans &lt;strong&gt;un fichier texte&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;(manuel) je &lt;strong&gt;commite et pousse sur Gitea/Github/Gitlab&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;(automatique) la plateforme de réception &lt;strong&gt;envoie un appel&lt;/strong&gt; à un de mes serveurs&lt;/li&gt;
&lt;li&gt;(automatique) un de mes serveurs reçevant l&amp;rsquo;appel &lt;strong&gt;lance un script&lt;/strong&gt; ou une action &lt;strong&gt;pour publier&lt;/strong&gt; les dernières nouveautés&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Parfait on se lance là dedans !&lt;/p&gt;
&lt;h1 id=&#34;la-naissance-de-gachette&#34;&gt;La naissance de Gachette&lt;/h1&gt;
&lt;p&gt;En 2019 où j&amp;rsquo;étudiais la question, je ne trouvais pas de serveur simple et léger qui puisse supporter les appels envoyés par Github, Gitlab et Gitea. &lt;strong&gt;Hors de question d&amp;rsquo;avoir 3 serveurs de webhooks différents sur mes machines&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Comme j&amp;rsquo;ai cru comprendre être ingénieur logiciel au travail &amp;#x1f923;, je me suis dit pouvoir l&amp;rsquo;être aussi à la maison sur mon temps personnel. À l&amp;rsquo;époque je m&amp;rsquo;amusais un peu avec le &lt;a href=&#34;https://crystal-lang.org/&#34;&gt;langage Crystal&lt;/a&gt; avec des amis, c&amp;rsquo;était l&amp;rsquo;occasion.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est ainsi qu&amp;rsquo;est né &lt;a href=&#34;https://github.com/blankoworld/gachette&#34;&gt;Gachette&lt;/a&gt;, un serveur de webhooks sous Licence MIT en &lt;a href=&#34;https://crystal-lang.org/&#34;&gt;Crystal&lt;/a&gt; (une syntaxe comme Ruby, mais compilé) qui supporte les plateformes Github, Gitlab et Gitea.&lt;/p&gt;
&lt;p&gt;Sous ce langage, il existe quelques &lt;a href=&#34;https://fr.wikipedia.org/wiki/Framework&#34;&gt;frameworks&lt;/a&gt;, dont &lt;a href=&#34;https://kemalcr.com/&#34;&gt;Kemal, un framework web minimaliste&lt;/a&gt; qui permet d&amp;rsquo;ouvrir quelques routes très facilement. C&amp;rsquo;est ce que j&amp;rsquo;ai utilisé pour créer &lt;a href=&#34;https://github.com/blankoworld/gachette/releases/tag/0.1&#34;&gt;la première version 0.1 de Gachette en 2019&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;À tout casser on doit être à 100 lignes de code. Bref. À aujourd&amp;rsquo;hui, plutôt 200+ lignes de code Crystal.&lt;/p&gt;
&lt;p&gt;Voyons les particularités de mise en place de Gachette.&lt;/p&gt;
&lt;h1 id=&#34;mise-en-place-de-gachette-sur-un-serveur&#34;&gt;Mise en place de Gachette sur un serveur&lt;/h1&gt;
&lt;p&gt;Je ne vais pas reproduire &lt;a href=&#34;https://github.com/blankoworld/gachette/blob/master/README.md#installation&#34;&gt;ce que le fichier README de Gachette énonce si bien pour l&amp;rsquo;installation&lt;/a&gt;, cependant je peux vous faire un résumé rapide de l&amp;rsquo;installation/configuration :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# On récupère le projet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone https://github.com/blankoworld/gachette.git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd gachette
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Pré-requis : Crystal, Shards et make doivent être installés&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;shards install
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# On compile le logiciel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;À l&amp;rsquo;issue de ces commandes devrait apparaître un fichier &lt;strong&gt;bin/gachette&lt;/strong&gt; qui est un exécutable utilisable tel quel.&lt;/p&gt;
&lt;p&gt;On le place où on veut, par exemple dans &lt;strong&gt;/srv/www/gachette/gachette&lt;/strong&gt; puis on édite le fichier &lt;strong&gt;/etc/systemd/system/gachette.service&lt;/strong&gt; dont le contenu est le suivant :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-service&#34; data-lang=&#34;service&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Description&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Gachette webhooks service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;After&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;network.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Type&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;User&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;http&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;WorkingDirectory&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/srv/www/gachette&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ExecStart&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/srv/www/gachette/gachette -c /etc/gachette.ini -b 0.0.0.0 -p 3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Environment&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;KEMAL_ENV=production&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Restart&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;WantedBy&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;À noter qu&amp;rsquo;il faut adapter &lt;strong&gt;User=http&lt;/strong&gt; par l&amp;rsquo;utilisateur de votre système d&amp;rsquo;exploitation, par exemple sous Debian c&amp;rsquo;est &lt;em&gt;User=www-data&lt;/em&gt;. Mais également le port utilisé, ici c&amp;rsquo;est le port &lt;strong&gt;3000&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Ensuite créez le fichier &lt;strong&gt;/etc/gachette.ini&lt;/strong&gt; avec un contenu qui va décrire les dépôts/projets qui vont contacter le serveur webhooks et déclencher une action. Imaginons que le projet Gachette, sur Github, à l&amp;rsquo;adresse &lt;a href=&#34;https://github.com/blankoworld/gachette&#34;&gt;https://github.com/blankoworld/gachette&lt;/a&gt; veuille qu&amp;rsquo;à chaque commit nous exécutions le contenu du script &lt;em&gt;/srv/www/gachette/deploiement.sh&lt;/em&gt;, nous allons écrire :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# contenu du fichier /etc/gachette.ini&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;Un_nom_au_hasard&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;service &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; github
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;namespace &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; blankoworld/gachette
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;key &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; monMot2Passe
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;scriptfile &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; /srv/www/gachette/deploiement.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Une fois la configuration faite, le service installé, vous pouvez faire en tant qu&amp;rsquo;utilisateur root :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# pour lancer le service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl start gachette.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# pour voir l&amp;#39;état du service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl status gachette.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# pour lancer le service à chaque redémarrage : &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl enable gachette.service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# pour suivre ce qu&amp;#39;il se passe dans Gachette : &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;journalctl -xe -f -u gachette.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tout résidera ensuite dans &lt;strong&gt;votre capacité à créer des scripts qui feront le travail de déploiement&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Dans ma situation, pour le présent blog, j&amp;rsquo;ai un script qui :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;récupère la dernière version du dépôt Git du blog&lt;/li&gt;
&lt;li&gt;compile le site pour générer les fichiers statiques&lt;/li&gt;
&lt;li&gt;synchronise le résultat - si réussi - vers un dossier particulier&lt;/li&gt;
&lt;li&gt;relance le serveur Web avec les nouveaux fichiers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Suite à &lt;a href=&#34;https://olivier.dossmann.net/2022/12/utilisation-de-tr%C3%A6fik-pour-publier-ses-conteneurs-docker/&#34;&gt;mon dernier article sur Træfik pour publier ses conteneurs Docker&lt;/a&gt;, je me suis même essayé à l&amp;rsquo;utilisation de conteneurs Docker pour isoler les environnements, voire même à avoir des images Docker communes pour l&amp;rsquo;ensemble des sites Web statiques : très pratique !&lt;/p&gt;
&lt;p&gt;On s&amp;rsquo;amuse bien par ici en somme &amp;#x1f609;.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Bien que certains jugerons ma chaîne de publication assez alambiquée, utilisant des outils peu communs, voire pas du tout utilisés (Gachette notamment), ce système a déjà fait ses preuves et tourne bien : moins d&amp;rsquo;une minute après avoir enregistré un article, il est publié sur le web sans action humaine.&lt;/p&gt;
&lt;p&gt;Il n&amp;rsquo;y a pour cela que 3 outils simples :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gitea comme dépôt Git ; qui déclenche une demande auprès d&amp;rsquo;un serveur distant (ici Gachette)&lt;/li&gt;
&lt;li&gt;Gachette qui reçoit la demande et lance un script de compilation/déploiement/traitement (bref, une action est menée)&lt;/li&gt;
&lt;li&gt;Nginx comme serveur Web pour diffuser les pages statiques ainsi générées&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L&amp;rsquo;utilisation de Docker en sus améliore le côté réutilisable des outils : pour plusieurs sites statiques j&amp;rsquo;utilise la même image qui va compiler les fichiers puis les mettre à disposition sur le net.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;La difficulté réside cependant à notre capacité à créer des scripts&lt;/strong&gt; pour lancer les différentes actions sur le serveur. La ligne de commande et Bash sont de fidèles alliés !&lt;/p&gt;
&lt;h1 id=&#34;liens-utiles&#34;&gt;Liens utiles&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.github.com/fr/webhooks-and-events/webhooks/creating-webhooks&#34;&gt;Configurer un Webhook sur Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#configure-a-webhook-in-gitlab&#34;&gt;Configure a webhook in Gitlab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.gitea.io/en-us/usage/webhooks/&#34;&gt;Gitea Webhooks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
	    <title>Utilisation de træfik pour publier ses conteneurs Docker</title>
      <link>https://olivier.dossmann.net/2022/12/utilisation-de-tr%C3%A6fik-pour-publier-ses-conteneurs-docker/</link>
      <pubDate>Wed, 07 Dec 2022 07:16:11 +0100</pubDate>
      
      <guid>https://olivier.dossmann.net/2022/12/utilisation-de-tr%C3%A6fik-pour-publier-ses-conteneurs-docker/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Il y a 8 ans &lt;a href=&#34;https://olivier.dossmann.net/2014/04/voici-docker-plus-l%C3%A9ger-et-plus-simple-quune-machine-virtuelle/&#34;&gt;je vous faisais découvrir Docker&lt;/a&gt;. À l&amp;rsquo;époque je ne savais pas encore à quel point cet outil très controversé serait utilisé !&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.docker.com/&#34;&gt;Docker&lt;/a&gt; est quasiment devenu un standard. Qu&amp;rsquo;on le veuille ou non il arrive souvent qu&amp;rsquo;on ait un conteneur Docker à lancer. On finit toujours par devoir lire la &lt;a href=&#34;https://docs.docker.com/get-started/&#34;&gt;documentation de Docker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Avant de continuer sur la problématique du présent article, je tiens à vous signaler qu&amp;rsquo;il est important de savoir un minimum jouer avec les fichiers &lt;strong&gt;docker-compose.yml&lt;/strong&gt;. Cas échéant je crains que cet article ne vous soit d&amp;rsquo;aucune autre utilité que nourrir votre curiosité.&lt;/p&gt;
&lt;p&gt;Ainsi, un problème qui survient fréquemment quand on a crée nos images, nos conteneurs puis que nous lançons ces derniers : comment publier nos conteneurs afin qu&amp;rsquo;ils soient disponibles sur Internet ? En général la solution est d&amp;rsquo;utiliser un proxy (par exemple &lt;a href=&#34;https://nginx.org/en/docs/&#34;&gt;Nginx&lt;/a&gt;) qui va étudier les requêtes HTTP demandées sur le serveur puis rediriger vers le port choisi d&amp;rsquo;un conteneur Docker qu&amp;rsquo;on a lancé.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/logos/traefik.png&#34; alt=&#34;Image du logo de Traefik&#34;&gt;&lt;/p&gt;
&lt;p&gt;Dans cet article je vais rapidement expliquer pourquoi le choix de &lt;a href=&#34;https://traefik.io/&#34;&gt;Træfik&lt;/a&gt; plutôt que Nginx que j&amp;rsquo;utilisais avant ça. Ensuite j&amp;rsquo;expliquerai les configurations utilisées pour mettre à disposition nos conteneurs. Nous aborderons rapidement quelques points pour aller plus loin et finirons par une conclusion.&lt;/p&gt;
&lt;h1 id=&#34;choix-du-proxy&#34;&gt;Choix du proxy&lt;/h1&gt;
&lt;p&gt;Habituellement, pour mettre en place l&amp;rsquo;accès à des sites web que j&amp;rsquo;héberge, j&amp;rsquo;utilisais &lt;a href=&#34;https://httpd.apache.org/&#34;&gt;Apache&lt;/a&gt;, &lt;a href=&#34;https://www.nginx.com/&#34;&gt;Nginx&lt;/a&gt; ou encore &lt;a href=&#34;https://caddyserver.com/&#34;&gt;Caddy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cependant il y avait pas mal de contraintes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;chaque nouveau domaine demandait une configuration spécifique avec un fichier spécifique, des dossiers spécifiques,&lt;/li&gt;
&lt;li&gt;pour avoir un certificat SSL par &lt;a href=&#34;https://letsencrypt.org/&#34;&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt;, il fallait parfois user d&amp;rsquo;intelligence, même une fois qu&amp;rsquo;on utilise &lt;a href=&#34;https://certbot.eff.org/&#34;&gt;Certbot&lt;/a&gt;, notamment pour redémarrer le serveur Web une fois les certificats renouvelés,&lt;/li&gt;
&lt;li&gt;quand on lançait un conteneur Docker, il valait mieux choisir un port spécifique, par exemple 8081, puis recopier ce nombre &lt;strong&gt;en dur&lt;/strong&gt; dans la configuration du serveur Web (Nginx dans mon cas) et je ne suis pas le plus imaginatif pour les numéros de ports qui se cumulaient…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce qui est assez pénible. Très consommateur de temps.&lt;/p&gt;
&lt;p&gt;Étant donné que nous utilisons déjà les possibilités de Docker et Docker Compose, autant continuer en utilisant un outil ayant un backend avec Docker, non ?&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est là que Træfik entre en jeu :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;il permet &lt;strong&gt;avec quelques lignes dans vos fichiers docker-compose.yml&lt;/strong&gt; de &lt;strong&gt;définir le domaine à utiliser&lt;/strong&gt; pour tel ou tel conteneur Docker&lt;/li&gt;
&lt;li&gt;il s&amp;rsquo;occupe de &lt;strong&gt;faire la demande de certificat Let&amp;rsquo;s Encrypt et le renouvellement&lt;/strong&gt; de ces derniers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;le lancement d&amp;rsquo;un conteneur Docker ne demande pas de relancer Træfik&lt;/strong&gt;, il y a une détection automatique des configurations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;on laisse les ports choisis par Docker pour nos conteneurs&lt;/strong&gt;, ce qui nous évite d&amp;rsquo;en faire une gestion&lt;/li&gt;
&lt;li&gt;étant codé en Go (tout comme Docker et Docker Compose), Træfik fait partie du même monde, il est donc aussi rapide et compatible avec les outils utilisés&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pas besoin d&amp;rsquo;installer Træfik&lt;/strong&gt; : il sera un conteneur Docker comme le reste des services de la machine &amp;#x1f603;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Au final ce sont les contraintes des serveurs Web dont j&amp;rsquo;ai eu l&amp;rsquo;usage qui m&amp;rsquo;ont convaincu d&amp;rsquo;essayer Træfik. Voyons donc à quoi cela ressemble !&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ATTENTION&lt;/strong&gt; : Træfik ne résoud pas tous les problèmes du monde. Il va falloir expérimenter, recommencer plusieurs fois, plier son cerveau pour saisir de quoi il retourne. Parfois demander de l&amp;rsquo;aide. C&amp;rsquo;est un processus d&amp;rsquo;apprentissage qui en vaut la peine cependant !&lt;/p&gt;
&lt;h1 id=&#34;configuration-de-træfik&#34;&gt;Configuration de træfik&lt;/h1&gt;
&lt;p&gt;Pour mettre en place Træfik nous allons procéder comme la &lt;a href=&#34;https://doc.traefik.io/traefik/&#34;&gt;documentation de Træfik Proxy&lt;/a&gt; le propose :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;faire un &lt;strong&gt;docker-compose.yml&lt;/strong&gt; pour décrire notre service Træfik&lt;/li&gt;
&lt;li&gt;utiliser un fichier de configuration externe pour configurer le service : le fichier &lt;strong&gt;traefik.yml&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;demander à exposer les ports 80 et 443&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour cela, voici le fichier &lt;strong&gt;docker-compose.yml&lt;/strong&gt; pour lancer le service Træfik :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-docker-compose&#34; data-lang=&#34;docker-compose&#34;&gt;version: &amp;#39;3&amp;#39;

services:
    proxy:
      image: traefik:v2.8
      restart: always
      ports:
      	- 80:80
        - 443:443
      volumes:
        # pour que Træfik écoute les événements Docker : à adapter chez vous
        - /var/run/docker.sock:/var/run/docker.sock
        # Utilisation d&amp;#39;un fichier de configuration
        - ${PWD}/traefik.yml:/etc/traefik/traefik.yml
        # Mémorisation des certificats TLS (par Let&amp;#39;s Encrypt)
        - ${PWD}/acme.json:/acme.json
      labels:
        # Activation du tls
        - &amp;#34;traefik.http.routers.api.tls&amp;#34;
        # nawak, pour que les logs la boucle sur service error: port is missing
        - &amp;#34;traefik.http.services.nawak.loadbalancer.server.port=8484&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ce qui va monter le fichier local &lt;strong&gt;/var/run/docker.sock&lt;/strong&gt; pour discuter avec Docker : adaptez-le au fichier Socket de votre service Docker.&lt;/p&gt;
&lt;p&gt;Cela va utiliser le fichier &lt;strong&gt;traefik.yml&lt;/strong&gt; local qui contient notre configuration pour notre service Træfik.&lt;/p&gt;
&lt;p&gt;On stocke les données des certificats dans le fichier local &lt;strong&gt;acme.json&lt;/strong&gt; : pensez à faire &lt;code&gt;touch acme.json&lt;/code&gt; pour créer le fichier avant de lancer.&lt;/p&gt;
&lt;p&gt;Et voici le contenu de notre fichier &lt;strong&gt;traefik.yml&lt;/strong&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;api&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;dashboard&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# pour activer un tableau de bord&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;providers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;docker&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;network&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;traefik&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# réseau de discussion entre les conteneurs et traefik&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;exposedByDefault&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# n&amp;#39;active pas les conteneurs par défaut sur le web&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;entryPoints&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;web&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;address&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;:80&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;http&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;redirections&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;entryPoint&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;to&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;websecure&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# pointe sur websecure plus bas (port 443 en somme)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;scheme&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;https&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;websecure&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;address&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;:443&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;http&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;tls&lt;/span&gt;: &lt;span style=&#34;color:#75715e&#34;&gt;# configuration par défaut&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;certResolver&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;letsencrypt&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# pointe sur la config. letsencrypt plus bas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;traefik&lt;/span&gt;: &lt;span style=&#34;color:#75715e&#34;&gt;# adresse pour le dashboard ;-)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;address&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;:8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;certificatesResolvers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;letsencrypt&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;acme&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;email&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mon-courriel@domaine.tld&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;storage&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/acme.json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;httpChallenge&lt;/span&gt;: &lt;span style=&#34;color:#75715e&#34;&gt;# le type utilisé pour valider les certificats Let&amp;#39;s Encrypt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;entryPoint&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;web&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Je me suis permis de commenter un peu partout pour savoir de quoi il retourne.&lt;/p&gt;
&lt;p&gt;Sachez qu&amp;rsquo;il existe aussi une méthode pour créer un fichier sur lequel Traefik va lire régulièrement pour mettre à jour sa configuration. Peut-être ferais-je un autre article sur ce sujet un jour. Petite piste : c&amp;rsquo;est le &lt;a href=&#34;https://doc.traefik.io/traefik/providers/file/&#34;&gt;&lt;em&gt;Provider&lt;/em&gt; nommé &lt;strong&gt;file&lt;/strong&gt;&lt;/a&gt; qui permet de faire ça.&lt;/p&gt;
&lt;p&gt;Une fois configuré, les autres conteneurs Docker que nous lançons n&amp;rsquo;ont plus besoin que des lignes suivantes dans &lt;strong&gt;leur fichier docker-compose.yml&lt;/strong&gt; :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-docker-compose&#34; data-lang=&#34;docker-compose&#34;&gt;labels:
  - &amp;#34;traefik.enable=true&amp;#34;
  - &amp;#34;traefik.http.routers.un-nom-de-service.rule=Host(`mon.domaine.com`)&amp;#34;
  - &amp;#34;traefik.http.routers.un-nom-de-service.entrypoints=websecure&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Au lancement de vos conteneurs via un fichier docker-compose.yml, Træfik lira les informations contenues dans &lt;strong&gt;labels&lt;/strong&gt; et tentera de les analyser puis utiliser à bon essien.&lt;/p&gt;
&lt;p&gt;Dans l&amp;rsquo;exemple donné ci-avant, on comprend que :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;trafik.enable : le service doit être publié par Traefik (car dans la configuration nous avions mis &lt;code&gt;exposedByDefault: false&lt;/code&gt;, donc pas de publication par défaut)&lt;/li&gt;
&lt;li&gt;traefik.http.routers.un-nom-de-service.rule=Host(`mon.domaine.com`) : pour votre service remplacez un-nom-de-service par ce que vous voulez. Et &lt;strong&gt;mon.domaine.com&lt;/strong&gt; par le domaine que vous détenez&lt;/li&gt;
&lt;li&gt;la dernière ligne ne sert qu&amp;rsquo;à indiquer quel entrée par défaut accepter/utiliser. En l&amp;rsquo;occurence celle nommée &lt;em&gt;websecure&lt;/em&gt; qui, dans notre configuration du fichier traefik.yml est configurée pour être disponible sur le port 443 avec un résolveur de certificat Let&amp;rsquo;s Encrypt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Exemple de docker-compose.yml pour lancer un service :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-docker-compose&#34; data-lang=&#34;docker-compose&#34;&gt;version: &amp;#39;3&amp;#39;

services:
    whoami:
      image: traefik/whoami
      labels:
        - &amp;#34;traefik.enable=true&amp;#34;
        - &amp;#34;traefik.http.routers.whoami.rule=Host(`whoami.domaine.com`)&amp;#34;
        - &amp;#34;traefik.http.routers.whoami.entrypoints=websecure&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Y aurait-il encore d&amp;rsquo;autres fonctionnalités sympas ?&lt;/p&gt;
&lt;h1 id=&#34;pour-aller-plus-loin&#34;&gt;Pour aller plus loin&lt;/h1&gt;
&lt;p&gt;Dans ce que j&amp;rsquo;ai pratiqué, voici quelques points à étudier pour aller plus loin :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;utilisation de &lt;a href=&#34;https://doc.traefik.io/traefik/https/acme/#dnschallenge&#34;&gt;Let&amp;rsquo;s Encrypt par challenge DNS&lt;/a&gt; qui permet de gérer les DNS de son fournisseur de domaine en direct. Par exemple pour Gandi il suffit de fournir la variable d&amp;rsquo;environnement GANDIV5_API_KEY&lt;/li&gt;
&lt;li&gt;utilisation d&amp;rsquo;un fichier externe avec &lt;code&gt;watch: true&lt;/code&gt; pour appliquer les changements dès modification du fichier&lt;/li&gt;
&lt;li&gt;utilisation de middleware pour une authentification basique&lt;/li&gt;
&lt;li&gt;activer un port, par exemple 8080 pour l&amp;rsquo;accès au tableau de bord&lt;/li&gt;
&lt;li&gt;dans certains cas où les services ne sont pas forcément dans des Docker, il peut être intéressant de fournir une IP et un port spécifique par un loadBalancer, Cf. &lt;a href=&#34;https://doc.traefik.io/traefik/routing/services/#servers&#34;&gt;https://doc.traefik.io/traefik/routing/services/#servers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il y a beaucoup plus à découvrir avec Træfik. Je vous invite à &lt;a href=&#34;https://doc.traefik.io/traefik/&#34;&gt;lire la documentation&lt;/a&gt; qui est très riche et bien expliquée.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Utiliser Træfik a permis de réduire considérablement le temps de maintenance de mes services, que ce soit en terme de mises à jour, de renouvellement de certificats et d&amp;rsquo;organisation des dossiers/fichiers.&lt;/p&gt;
&lt;p&gt;Cependant qu&amp;rsquo;on se le dise, ce n&amp;rsquo;est pas exempt de quelques difficultés :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;il n&amp;rsquo;y a pas toujours des images Docker de vos services, il faut donc parfois fabriquer soi-même les conteneurs,&lt;/li&gt;
&lt;li&gt;la courbe d&amp;rsquo;apprentissage de Træfik est assez difficile,&lt;/li&gt;
&lt;li&gt;on se casse les méninges jusqu&amp;rsquo;à comprendre comment fournir un service sur Træfik&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si on fait l&amp;rsquo;effort d&amp;rsquo;apprendre Træfik et d&amp;rsquo;investir du temps, c&amp;rsquo;est surtout pour assurer la possibilité de connecter tout cela à un &lt;a href=&#34;https://doc.traefik.io/traefik/observability/metrics/overview/&#34;&gt;système de métriques&lt;/a&gt;, pouvoir faire de la journalisation, vérifier l&amp;rsquo;état de santé des serveurs, etc.&lt;/p&gt;
&lt;p&gt;Il y a de quoi faire !&lt;/p&gt;
</description>
    </item>
    
    <item>
	    <title>Jeu, Dreamlight Valley</title>
      <link>https://olivier.dossmann.net/2022/11/jeu-dreamlight-valley/</link>
      <pubDate>Fri, 04 Nov 2022 21:58:39 +0100</pubDate>
      
      <guid>https://olivier.dossmann.net/2022/11/jeu-dreamlight-valley/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Dans &lt;a href=&#34;https://olivier.dossmann.net/2022/09/%C3%A9tat-des-lieux-2022/&#34;&gt;l&amp;rsquo;état des lieux 2022 de mon espace numérique&lt;/a&gt; (un précédent article de ce blog) j&amp;rsquo;énonçais DreamLight Valley, un jeu vidéo Disney créé par &lt;a href=&#34;https://www.gameloft.com/&#34;&gt;GameLoft&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Parlons un peu de &lt;a href=&#34;https://fr.wikipedia.org/wiki/Disney_Dreamlight_Valley&#34;&gt;DreamLight Valley&lt;/a&gt;, décrivons le un peu pour ensuite s&amp;rsquo;intéresser à quelques éléments de la composition du jeu. Puis nous donnerons notre avis avant de conclure sur cet article.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/jeux/dreamlight-valley-DDV_001.jpg&#34; alt=&#34;Image de DreamLight Valley&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;description&#34;&gt;Description&lt;/h1&gt;
&lt;p&gt;Qu&amp;rsquo;est DreamLight Valley ? C&amp;rsquo;est un jeu vidéo sorti en accès anticipé en France le 6 septembre 2022. Disponible sur de nombreuses consoles comme Microsoft Xbox, Nintendo Switch, PC et Playstation 4 et 5.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est un jeu à la troisième personne où le joueur évolue dans un monde en 3 dimensions et doit effectuer des quêtes pour avancer dans l&amp;rsquo;histoire.&lt;/p&gt;
&lt;p&gt;Vous êtes le héros principal de cette histoire et arrivez dans un univers qui a été frappé par l&amp;rsquo;Oubli : tous les personnages ont perdu la mémoire et plusieurs maléfices parcourent ce monde.&lt;/p&gt;
&lt;p&gt;Comme dans beaucoup de jeux vous allez devoir sauver ce monde, lever les maléfices, nettoyer l&amp;rsquo;endroit et faire recouvrir la mémoire aux personnages autour de vous.&lt;/p&gt;
&lt;p&gt;Quelques exemples de personnages :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mickey,&lt;/li&gt;
&lt;li&gt;Picsou,&lt;/li&gt;
&lt;li&gt;Merlin l&amp;rsquo;enchanteur,&lt;/li&gt;
&lt;li&gt;Wall-E,&lt;/li&gt;
&lt;li&gt;Dingo,&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce jeu est fait pour les enfants, il n&amp;rsquo;y a donc pas de système de combats. Et vous évoluez dans un monde où vous devez travailler sur l&amp;rsquo;amour, l&amp;rsquo;amitié, etc. C&amp;rsquo;est à dire que vous allez devoir cultiver vos amitiés avec les différents protagonistes.&lt;/p&gt;
&lt;p&gt;Dans ce jeu, vous avez plusieurs &amp;ldquo;monnaies&amp;rdquo; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;des pièces d&amp;rsquo;or quand vous vendez/achetez des graines/fruits/légumes/autres aux stands de Dingo&lt;/li&gt;
&lt;li&gt;des points Dreamlight à utiliser pour débloquer des parties de l&amp;rsquo;univers ou bien ouvrir des portes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;D&amp;rsquo;autres points font penser à d&amp;rsquo;autres jeux vidéos connus.&lt;/p&gt;
&lt;h1 id=&#34;éléments-du-jeu&#34;&gt;Éléments du jeu&lt;/h1&gt;
&lt;p&gt;Qu&amp;rsquo;on se le dise, DreamLight Valley n&amp;rsquo;invente rien en la matière :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on retrouve le système d&amp;rsquo;outils de Stardew Valley comme la pioche, l&amp;rsquo;arrosoir, la pelle pour interagir avec l&amp;rsquo;univers dans lequel on se trouve&lt;/li&gt;
&lt;li&gt;on discute avec les personnes comme dans beaucoup de jeux de rôle, on pourrait même penser au jeu « Les Sims »&lt;/li&gt;
&lt;li&gt;il y a un peu du Animal Crossing dans la façon de présenter les quêtes journalières pour obtenir des points&lt;/li&gt;
&lt;li&gt;le château et ses portes pour transiter vers d&amp;rsquo;autres univers fait penser à Mario 64&lt;/li&gt;
&lt;li&gt;le choix des outils sur un cercle au milieu de l&amp;rsquo;écran fait penser à Fortnite&lt;/li&gt;
&lt;li&gt;le système de différentes monnaies fait penser à Animal Crossing&lt;/li&gt;
&lt;li&gt;on cultive des légumes comme dans Stardew Valley&lt;/li&gt;
&lt;li&gt;on décore la maison comme dans Animal Crossing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le jeu est donc assez commun dans ses comportements et les éléments du jeu sont assez vus partout ailleurs pour ne pas se sentir dépaysé !&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est dans ce système que nous avons évolué et nous allons exprimer notre ressenti à ce sujet.&lt;/p&gt;
&lt;h1 id=&#34;avis&#34;&gt;Avis&lt;/h1&gt;
&lt;p&gt;Bon enfant, ce jeu est purement et simplement de la détente où on évolue dans un univers où il fait bon vivre, bien qu&amp;rsquo;on commence la partie de nuit, dans un monde tombé dans l&amp;rsquo;Oubli où même Merlin l&amp;rsquo;enchanteur ne se souvient plus de grand chose.&lt;/p&gt;
&lt;p&gt;La particularité de ce jeu ira surtout dans le fait de se lier d&amp;rsquo;amitié avec les personnages, de leur faire de bons petits plats avec les ingrédients récoltés ici ou là, de pêcher, de planter, arroser, cueillir, etc.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est agréable, on apprécie !&lt;/p&gt;
&lt;p&gt;Cependant le jeu étant encore en accès anticipé, le contenu est encore limité : même avec 18 personnages (depuis une mise à jour récente) les quêtes sont vites finies.&lt;/p&gt;
&lt;p&gt;Au départ la difficulté est assez grande pour obtenir des DreamLight et pouvoir débloquer les parties de la carte pour accéder à de nouveaux personnages et nouvelles denrées. Mais avec quelques habitudes on arrive ensuite à cumuler assez de DreamLight pour continuer sereinement.&lt;/p&gt;
&lt;p&gt;Dans la partie on récupère des morceaux de souvenirs mais on ne sait pas à quoi cela sert pour le moment.&lt;/p&gt;
&lt;p&gt;Il y a aussi des quêtes événementielles qui permettent de débloquer des objets spécifiques à l&amp;rsquo;événement pour les joueurs. D&amp;rsquo;un point de vue &amp;ldquo;monnaie&amp;rdquo;, ils ne sont pas du tout intéressants, mais il reste facile de les débloquer sur la période limitée. À condition de jouer un peu tous les jours évidemment.&lt;/p&gt;
&lt;p&gt;On regrette aussi beaucoup d&amp;rsquo;être interrompu une fois par jour (voire plus) pour des bugs du jeu qui se fige, s&amp;rsquo;arrête carrément sous Nintendo Switch sans avoir sauvegardé ! Très pénible. Mais le jeu étant en accès anticipé, on se fait une raison.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Bien que nous ayons un jeu simple et bon enfant, avec de quoi s&amp;rsquo;occuper la journée, les nombreux bugs du début et la rapidité de finition des quêtes nous laisse beaucoup sur notre faim !&lt;/p&gt;
&lt;p&gt;En revanche le monde de Disney nous rappelant beaucoup de souvenirs - et on imagine bien que Disney s&amp;rsquo;appuie là dessus pour vendre des produits dérivés - on a hâte de savoir quels seront les prochains personnages et comment les débloquer au plus vite lors des prochaines mises à jour !&lt;/p&gt;
</description>
    </item>
    
    <item>
	    <title>Cron sous Docker avec Alpine</title>
      <link>https://olivier.dossmann.net/2022/10/cron-sous-docker-avec-alpine/</link>
      <pubDate>Wed, 12 Oct 2022 21:41:39 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2022/10/cron-sous-docker-avec-alpine/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Chose promie, chose due ! J&amp;rsquo;écris un article sur mes pérégrinations en informatique.&lt;/p&gt;
&lt;p&gt;Cette fois, je fais suite à &lt;a href=&#34;https://olivier.dossmann.net/2022/09/%C3%A9tat-des-lieux-2022/&#34;&gt;l&amp;rsquo;état des lieux 2022 de mon espace numérique&lt;/a&gt;. Certains de mes services/sites nécessitent régulièrement d&amp;rsquo;être mis à jour. Pour cela je souhaite utiliser &lt;strong&gt;Cron, un service sous GNU/Linux qui permet de planifier le lancement de script(s) à des fréquences définies&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Comme je souhaite utiliser Docker, je me suis demandé s&amp;rsquo;il était possible de créer un service dédié avec Cron, Docker et Alpine.&lt;/p&gt;
&lt;p&gt;Cet article explique quelques règles que j&amp;rsquo;ai dû suivre pour y parvenir. Il vous faudra a minima connaître Docker, voire Docker Compose pour comprendre quelque chose. À la rigueur vous connaissez déjà Cron et souhaitez l&amp;rsquo;utiliser sous Docker.&lt;/p&gt;
&lt;p&gt;Nous allons d&amp;rsquo;abord réflechir sur le sujet. Puis nous utiliserons l&amp;rsquo;exemple d&amp;rsquo;un site pour expliquer la solution choisie avant de conclure sur cette histoire.&lt;/p&gt;
&lt;p&gt;Pour les pressés, j&amp;rsquo;ai fais un chapitre « En bref » à la fin de cet article.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/objets/montre.jpg&#34; alt=&#34;Montre de poignet avec un stylo&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://flickr.com/photos/ducly/&#34;&gt;profil de Duc Ly sur Flickr&lt;/a&gt;&lt;/em&gt; sous licence CC BY-SA 2.0.&lt;/p&gt;
&lt;h1 id=&#34;réflexion-sur-le-sujet&#34;&gt;Réflexion sur le sujet&lt;/h1&gt;
&lt;p&gt;Ce que nous souhaitons faire, c&amp;rsquo;est lancer un service, par exemple &lt;strong&gt;almanax&lt;/strong&gt;, et le mettre à jour régulièrement avec une tâche dans le service &lt;strong&gt;cron&lt;/strong&gt;. Je vais expliquer un peu ma réflexion, si vous voulez entrer plus rapidement dans le vif du sujet, rendez-vous au chapitre suivant.&lt;/p&gt;
&lt;p&gt;Tout d&amp;rsquo;abord il faut savoir que &lt;strong&gt;l&amp;rsquo;environnement choisi est Docker&lt;/strong&gt;. Un système qui permet, &lt;strong&gt;à partir d&amp;rsquo;une image&lt;/strong&gt; de &lt;strong&gt;générer plusieurs conteneurs&lt;/strong&gt; ayant des points de montage différents pour changer les données qui s&amp;rsquo;y trouvent.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.docker.com/develop/dev-best-practices/&#34;&gt;Docker propose plusieurs bonnes pratiques&lt;/a&gt;, parmi lesquelles :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ne lancer qu&amp;rsquo;un seul processus/service dans chaque conteneur&lt;/li&gt;
&lt;li&gt;réutiliser les images ou les parties d&amp;rsquo;images au maximum pour réduire à la fois la maintenance des images/conteneurs, le travail effectué et la place système utilisée pour les images de base&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sachant que nous ne lançons qu&amp;rsquo;un seul processus par conteneur Docker, et que je souhaite utiliser Cron, je vais devoir lancer cron dans un autre service. Concrètement, Docker propose Docker Compose qui est un outil permettant de lancer plusieurs services à la fois, avec des dépendances entre eux (si besoin), une description des points de montage, des commandes à lancer sur chaque service, les ports ouverts, etc.&lt;/p&gt;
&lt;p&gt;On peut également choisir l&amp;rsquo;image qu&amp;rsquo;on souhaite utiliser pour chaque service.&lt;/p&gt;
&lt;p&gt;Certes nous allons lancer Cron dans un service à part, pour lancer les scripts que notre autre service a besoin pour mettre à jour ce dernier - je pense notamment à un script qui recompile et reconstitue mes pages webs statiques -, mais nous allons devoir avoir accès à notre service &lt;strong&gt;almanax&lt;/strong&gt; qui contient la logique principale du site.&lt;/p&gt;
&lt;p&gt;Pour cela, l&amp;rsquo;idée est de modifier l&amp;rsquo;image de &lt;strong&gt;almanax&lt;/strong&gt; pour qu&amp;rsquo;elle contienne elle aussi &lt;strong&gt;cron&lt;/strong&gt;. Ainsi on pourra lancer la même image sous Docker Compose, avec une commande de lancement différente.&lt;/p&gt;
&lt;p&gt;On utilise des services Docker. Chacun ayant déjà leur propre image sous Alpine. Ainsi, chaque image possède déjà Cron inclut dans Alpine.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;allais dire qu&amp;rsquo;une image vaut mieux que 1 000 mots, mais là nous allons donner un exemple avec Docker Compose pour comprendre de quoi il s&amp;rsquo;agit.&lt;/p&gt;
&lt;h1 id=&#34;mise-en-place-exemple-avec-lalmanax&#34;&gt;Mise en place, exemple avec l&amp;rsquo;Almanax&lt;/h1&gt;
&lt;p&gt;Peut-être le savez-vous déjà : j&amp;rsquo;ai crée une page statique qui liste une quinzaine de quêtes de l&amp;rsquo;Almanax dans un jeu nommé Dofus.&lt;/p&gt;
&lt;p&gt;Cet outil est un de mes services fourni aux utilisateurs, mais également &lt;a href=&#34;https://github.com/blankoworld/dofus-almanax&#34;&gt;un projet Open Source, dofus-almanax que je fournis via Github&lt;/a&gt;. C&amp;rsquo;est dans ce dépôt Github que vous trouverez la plupart des fichiers nécessaires au bon lancement d&amp;rsquo;un service Cron que nous allons décrire.&lt;/p&gt;
&lt;p&gt;On va étudier le fichier docker-compose.yml suivant :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;services:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  generator:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    build: .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    image: dofus-almanax:0.2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - almanax_public:/opt/almanax/public:rw
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - almanax_data:/opt/almanax/dl:rw
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  web:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    image: caddy:2-alpine
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    restart: always
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    depends_on:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - generator
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - almanax_public:/usr/share/caddy:ro
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;PWD&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;/Caddyfile:/etc/caddy/Caddyfile
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ports:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - 8888:80
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  cron:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    image: dofus-almanax:0.2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    restart: always
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    entrypoint: /usr/sbin/crond
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    command: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-f&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-l&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-L&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/dev/stdout&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - almanax_public:/opt/almanax/public:rw
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - almanax_data:/opt/almanax/dl:rw
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  almanax_public:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  almanax_data:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nous avons 3 services :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generator : qui génère le site web au lancement, suite à quoi il s&amp;rsquo;éteint,&lt;/li&gt;
&lt;li&gt;web : un service pour mettre à disposition les fichiers statiques générés par &lt;strong&gt;generator&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;cron : un service pour mettre à jour régulièrement les fichiers statiques.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La particularité de la solution :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;generator&lt;/strong&gt; et &lt;strong&gt;cron&lt;/strong&gt; utilisent la même image : dofus-almanax:0.2&lt;/li&gt;
&lt;li&gt;ces deux services n&amp;rsquo;ont cependant pas la même commande au lancement : l&amp;rsquo;un prend la commande par défaut de l&amp;rsquo;image dofus-almanax:0.2, l&amp;rsquo;autre lance spécifiquement cron&lt;/li&gt;
&lt;li&gt;pour le service &lt;strong&gt;cron&lt;/strong&gt;, il spécifie avec le mot clé &lt;strong&gt;entrypoint&lt;/strong&gt; d&amp;rsquo;utiliser &lt;strong&gt;/usr/sbin/crond&lt;/strong&gt; (chemin absolu du binaire sous Alpine) et donne les paramètres &lt;code&gt;-f -l 2 -L /dev/stdout&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Que font les paramètres ?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-f&lt;/code&gt; définit de lancer le service en &lt;code&gt;foreground&lt;/code&gt;, nécessaire sous Docker, sinon cela ne fonctionne pas&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-l 2&lt;/code&gt; définit un niveau de journalisation, habituellement c&amp;rsquo;est 8 (Cf. &lt;a href=&#34;https://unix.stackexchange.com/a/496741&#34;&gt;une explication des niveaux crond sous Stackoverflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-L /dev/stdout&lt;/code&gt; permet d&amp;rsquo;avoir une sortie à l&amp;rsquo;écran dans Docker Compose&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ça, c&amp;rsquo;est les éléments de base. Cependant comment fonctionne la mise à jour, la configuration de cette dernière, etc.?&lt;/p&gt;
&lt;h1 id=&#34;fonctionnement-de-cron-dans-limage-dofus-almanax02&#34;&gt;Fonctionnement de Cron dans l&amp;rsquo;image dofus-almanax:0.2&lt;/h1&gt;
&lt;p&gt;Nous l&amp;rsquo;avions dit, l&amp;rsquo;idée est de tout mettre dans l&amp;rsquo;image &lt;strong&gt;dofus-almanax:0.2&lt;/strong&gt; (à la fois nos scripts, nos fichiers &lt;strong&gt;et&lt;/strong&gt; crond). Mais comment configurer le service Cron pour lui indiquer la fréquence à laquelle mettre à jour et comment mettre à jour nos fichiers ?&lt;/p&gt;
&lt;p&gt;Regardons l&amp;rsquo;image Docker, écrite sous le fichier Dockerfile suivant :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;alpine:3.16&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; apk update &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    apk add --no-cache &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        py3-lxml &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	py3-mechanize &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	tzdata &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    rm -rf /var/cache/apk/*&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ENV&lt;/span&gt; TZ&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;Europe/Paris&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;/opt/almanax&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;VOLUME&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;/opt/almanax/public&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;VOLUME&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;/opt/almanax/dl&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ENTRYPOINT&lt;/span&gt; [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;python3&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;almanax_next_week.py&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CMD&lt;/span&gt; [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/opt/almanax/public/index.html&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;COPY&lt;/span&gt; ./src /opt/almanax&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;COPY&lt;/span&gt; ./crontabs /etc/crontabs/root&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; chown root:root /etc/crontabs/root &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chmod &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt; /etc/crontabs/root&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;COPY&lt;/span&gt; ./cron_scripts/generate.sh /opt/generate&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Étudions ce fichier dans les grandes lignes concernant le service Cron notamment.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Nous partons d&amp;rsquo;une &lt;strong&gt;image Alpine 3.16 qui contient déjà crond&lt;/strong&gt; (le service Cron)&lt;/li&gt;
&lt;li&gt;Nous installons &lt;strong&gt;tzdata&lt;/strong&gt; qui nous permettra de choisir correctement un fuseau horaire&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ENV TZ=Europe/Paris&lt;/code&gt; définit notre fuseau horaire, histoire de lancer le script au moment où nous nous y attendons&lt;/li&gt;
&lt;li&gt;Le fichier le plus important, &lt;strong&gt;cronbtabs&lt;/strong&gt; est copié vers &lt;strong&gt;/etc/crontabs/root&lt;/strong&gt;, la ligne &lt;code&gt;COPY ./crontabs /etc/crontabs/root&lt;/code&gt; est déterminante pour remplacer le fichier du service crond d&amp;rsquo;Alpine Linux&lt;/li&gt;
&lt;li&gt;On copie aussi un script &lt;strong&gt;generate.sh&lt;/strong&gt; dont nous parlerons après&lt;/li&gt;
&lt;li&gt;Ce même fichier nécessite des permissions spécifiques, notifiée vers la fin du fichier Dockerfile :&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; chown root:root /etc/crontabs/root &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chmod &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt; /etc/crontabs/root&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Que contient le fichier crontabs et generate.sh ?&lt;/p&gt;
&lt;h1 id=&#34;la-configuration-du-service-crond&#34;&gt;La configuration du service crond&lt;/h1&gt;
&lt;p&gt;Sous Alpine, le fichier  utilisé pour configurer les éléments à lancer par crond est &lt;strong&gt;/etc/crontabs/root&lt;/strong&gt;. Dans le chapitre précédent nous parlions de comment le remplacer, voici désormais son contenu :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;       &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;       *       *       *       /bin/sh /opt/generate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;Nous voyons que nous utilisons effectivement le script &lt;strong&gt;generate.sh&lt;/strong&gt; - qui a d&amp;rsquo;ailleurs été renommé &lt;strong&gt;generate&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Nous utilisons &lt;code&gt;/bin/sh&lt;/code&gt; devant notre script :
&lt;ul&gt;
&lt;li&gt;c&amp;rsquo;est un chemin absolu vers le binaire sh&lt;/li&gt;
&lt;li&gt;et nous utilisons sh, pas bash (car bash n&amp;rsquo;est, à défaut, pas délivré sous Alpine Linux)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Nous utilisons des caractères spécifique, formatés spécifiquement pour dire que nous lançons le service à 00h05 du matin&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pour générer un fichier compatible avec crond, je vous suggère &lt;a href=&#34;https://crontab-generator.org/&#34;&gt;Crontab Generator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Il va falloir appliquer quelques règles pour être sûr que tout cela fonctionne évidemment.&lt;/p&gt;
&lt;h1 id=&#34;en-bref-les-règles-à-appliquer-pour-crond&#34;&gt;En bref, les règles à appliquer pour crond&lt;/h1&gt;
&lt;p&gt;Voici les règles à retenir pour rédiger le fichier que le service crond va étudier :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;7 espaces entre chaque élément défini dans le crontab (le fichier se nomme ainsi)&lt;/li&gt;
&lt;li&gt;utiliser /bin/sh sous Alpine pour lancer un script, puis le nom de votre script&lt;/li&gt;
&lt;li&gt;ne pas mettre de point dans le script qu&amp;rsquo;on lance (mettre par exemple &lt;code&gt;generate&lt;/code&gt; au lieu de &lt;code&gt;generate.sh&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;le fichier &lt;code&gt;/etc/crontabs/root&lt;/code&gt; doit appartenir à root (&lt;code&gt;root:root&lt;/code&gt;) et avoir les permissions 600 (&lt;code&gt;chmod 600&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;utilisez &lt;code&gt;-L /dev/stdout&lt;/code&gt; sous votre Docker Compose pour avoir une sortie lisible et &lt;code&gt;-l 2&lt;/code&gt; pour plus de logs, mais &lt;code&gt;-l 8&lt;/code&gt; suffit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce qui fait déjà pas mal de choses à savoir !&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Bien que la réflexion ait été longue (et croyez moi j&amp;rsquo;ai pris plusieurs jours pour tester au fur et à mesure ce que je souhaitais), nous avons réuni les seules règles à appliquer pour que cela fonctionne, tout en trouvant une solution sympathique qui a plusieurs avantages :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;le service Cron accède à tous les fichiers communs de notre service initial&lt;/li&gt;
&lt;li&gt;le service Cron accède également à tous les scripts utiles de notre service initial&lt;/li&gt;
&lt;li&gt;il suffit de changer le script d&amp;rsquo;entrée de l&amp;rsquo;image initiale pour lancer Cron&lt;/li&gt;
&lt;li&gt;on a peu de changement à faire pour utiliser Cron finalement !&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L&amp;rsquo;inconvénient reste cependant qu&amp;rsquo;il faut pouvoir modifier l&amp;rsquo;image initiale. Si nous n&amp;rsquo;avions pas la possibilité de faire ça, j&amp;rsquo;imagine qu&amp;rsquo;on devrait créer un point de montage commun entre le service initial et le service cron pour accéder à la fois aux fichiers mais aussi aux binaires… ce qui est bien plus complexe/casse-tête !&lt;/p&gt;
&lt;h1 id=&#34;liens-utiles&#34;&gt;Liens utiles&lt;/h1&gt;
&lt;p&gt;Je me suis grandement inspiré, pour mes pérégrinations sur Cron dans Alpine sous Docker par :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://devopsheaven.com/cron/docker/alpine/linux/2017/10/30/run-cron-docker-alpine.html&#34;&gt;https://devopsheaven.com/cron/docker/alpine/linux/2017/10/30/run-cron-docker-alpine.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://mixu.wtf/cron-in-docker-alpine-image/&#34;&gt;https://mixu.wtf/cron-in-docker-alpine-image/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://crontab-generator.org/&#34;&gt;Crontab Generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
	    <title>Mise à jour des DNS Gandi (v5) avec la bbox de Bougues</title>
      <link>https://olivier.dossmann.net/2019/05/mise-%C3%A0-jour-des-dns-gandi-v5-avec-la-bbox-de-bougues/</link>
      <pubDate>Mon, 06 May 2019 20:18:29 +0200</pubDate>
      
      <guid>https://olivier.dossmann.net/2019/05/mise-%C3%A0-jour-des-dns-gandi-v5-avec-la-bbox-de-bougues/</guid>
      <description>&lt;p&gt;Figurez-vous qu&amp;rsquo;après &lt;a href=&#34;https://olivier.dossmann.net/2017/02/ivre-il-coupe-internet-episode-3/&#34;&gt;mes pérégrinations dans le monde de l&amp;rsquo;Internet nomade&lt;/a&gt;, j&amp;rsquo;ai eu l&amp;rsquo;occasion de passer à la Fibre. Et avec elle son lot de « malheurs » : une IP dynamique.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;En quoi est-ce problématique ?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une IP fixe permet de bénéficier d&amp;rsquo;une adresse constante, c&amp;rsquo;est à dire qu&amp;rsquo;elle permet, par exemple, d&amp;rsquo;avoir un nom de domaine qui redirige vers une à plusieurs machines de la maison. Par exemple avec &lt;strong&gt;bogossdu69.fr&lt;/strong&gt; je pourrais éventuellement arriver sur mon partage de fichiers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://olivier.dossmann.net/images/objets/expansion_lumi%C3%A8re.jpg&#34; alt=&#34;Expansion de lumière&#34; title=&#34;Des lampes de plafonds rectangulaires alignées pour former une étoile à 5 ou 6 branches&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo trouvée sur le &lt;a href=&#34;https://www.flickr.com/photos/sattygalle/&#34;&gt;profil de sattygalle sur Flickr&lt;/a&gt;&lt;/em&gt; sous licence CC BY-SA 2.0.&lt;/p&gt;
&lt;h1 id=&#34;la-situation&#34;&gt;La situation&lt;/h1&gt;
&lt;p&gt;Mon but est donc de mettre à jour régulièrement mes noms de domaine lorsque mon IP change.&lt;/p&gt;
&lt;p&gt;Je dispose de :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;une box Bouygues nommée &lt;strong&gt;bbox&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;une ip dynamique&lt;/li&gt;
&lt;li&gt;un nom de domaine chez Gandi.net&lt;/li&gt;
&lt;li&gt;une machine allumée en permanence sur la box&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;lobjectif&#34;&gt;L&amp;rsquo;objectif&lt;/h1&gt;
&lt;p&gt;Mettre à jour régulièrement le nom de domaine pour qu&amp;rsquo;il pointe vers ma box en permanence.&lt;/p&gt;
&lt;h1 id=&#34;ma-solution-en-1-commande&#34;&gt;Ma solution en 1 commande&lt;/h1&gt;
&lt;p&gt;En une commande :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s https://mabbox.bytel.fr/api/v1/wan/ip |jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.[0].wan.ip.address&amp;#39;&lt;/span&gt;| xargs -I&lt;span style=&#34;color:#f92672&#34;&gt;{}&lt;/span&gt; curl -X PUT -H &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;X-Api-key: LaSuperCleAPIdeGandiV5&amp;#34;&lt;/span&gt; -H &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{&amp;#34;rrset_ttl&amp;#34;:&amp;#34;1800&amp;#34;,&amp;#34;rrset_values&amp;#34;:[&amp;#34;{}&amp;#34;]}&amp;#39;&lt;/span&gt; https://dns.api.gandi.net/api/v5/domains/domain.tld/records/bogossdu69/A
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En remplaçant :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LaSuperCleAPIdeGandiV5&lt;/strong&gt; par la clé de sécurité dans votre interface Gandi sur &lt;em&gt;Tableau de Bord &amp;gt; Paramètres &amp;gt; Sécurité &amp;gt; (Re)Générer la clé d&amp;rsquo;API&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;domain.tld&lt;/strong&gt; par votre domaine, par exemple dossmann.net&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;bogossdu69&lt;/strong&gt; par votre sous-domaine, par exemple olivier (ce qui donnera olivier.dossmann.net)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;le-détail&#34;&gt;Le détail&lt;/h1&gt;
&lt;p&gt;L&amp;rsquo;idée est de lancer un script régulièrement (par exemple toutes les 5 minutes) sur la machine branchée à la Box.&lt;/p&gt;
&lt;p&gt;Pour cela on va utiliser les outils suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://mabbox.bytel.fr/api/v1/wan/ip&#34;&gt;l&amp;rsquo;IP donnée par l&amp;rsquo;API de votre bbox&lt;/a&gt; et dont la documentation est sur &lt;a href=&#34;https://api.bbox.fr/doc/apirouter/#api-WAN-GetWANIP&#34;&gt;le site officiel de l&amp;rsquo;API de Bouygues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;curl fourni dans la plupart des distributions GNU/Linux (et plus encore !)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stedolan.github.io/jq/&#34;&gt;jq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;l&amp;rsquo;outil timerctl fourni dans le système pour planifier l&amp;rsquo;exécution de tâches régulières&lt;/li&gt;
&lt;li&gt;et &lt;a href=&#34;https://github.com/blankoworld/divers/blob/master/maj_domaines_gandi.sh&#34;&gt;la commande précédente aménagée dans un script&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L&amp;rsquo;API de notre box va fournir l&amp;rsquo;IP publique dynamique de notre connexion internet. &lt;strong&gt;jq&lt;/strong&gt; va permettre la récupération de la bonne information parmi l&amp;rsquo;ensemble fourni par notre box. Après quoi &lt;strong&gt;curl&lt;/strong&gt; mettra à jour les DNS dynamiques de Gandi (notre fournisseur de nom de domaine).&lt;/p&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;rsquo;à taper la commande entière dans le fichier &lt;strong&gt;/etc/systemd/system/maj_domaine.service&lt;/strong&gt; sous la forme suivante :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Description&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Mise a jour du domaine Gandi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Environment&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;API_KEY=oefijzoifjzeoifjzeoifjeo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ExecStart&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/usr/bin/bash /home/user/maj_domaine.sh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Type&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;N&amp;rsquo;oubliez pas d&amp;rsquo;adapter &lt;strong&gt;API_KEY&lt;/strong&gt; avec votre clé d&amp;rsquo;API et &lt;strong&gt;/home/user/&lt;/strong&gt; par l&amp;rsquo;adresse où se trouve le script !&lt;/p&gt;
&lt;p&gt;Puis de renseigner le fichier &lt;strong&gt;/etc/systemd/system/maj_domaine.timer&lt;/strong&gt; avec :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Description&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Lance maj du domaine toutes les 8 min&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Timer]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;OnBootSec&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;8min&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;OnUnitActiveSec&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;8min&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Persistent&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Unit&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;maj_domaine.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;WantedBy&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il ne nous reste plus qu&amp;rsquo;à prévenir &lt;em&gt;systemd&lt;/em&gt; via les commandes suivantes :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl enable maj_domaine.timer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl start maj_domaine.timer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl start maj_domaine.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et le tour est joué !&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;À l&amp;rsquo;aide des outils listés dans ce billet on peut sans problème survivre à une IP dynamique à la maison chez Bouygues Telecom. Je n&amp;rsquo;ai eu jusqu&amp;rsquo;à ce jour aucun problème et espère que cela continuera ainsi.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
