<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nicolas KEMPF</title>
    <description>The latest articles on DEV Community by Nicolas KEMPF (@nicolaskempf57).</description>
    <link>https://dev.to/nicolaskempf57</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F354380%2F183ad081-27f1-4b20-8fd4-5ebe4a14f419.jpeg</url>
      <title>DEV Community: Nicolas KEMPF</title>
      <link>https://dev.to/nicolaskempf57</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nicolaskempf57"/>
    <language>en</language>
    <item>
      <title>Créez vos cartes interactives avec Vue.js et Leaflet</title>
      <dc:creator>Nicolas KEMPF</dc:creator>
      <pubDate>Wed, 30 Dec 2020 15:56:31 +0000</pubDate>
      <link>https://dev.to/nicolaskempf57/creez-vos-cartes-interactives-avec-vue-js-et-leaflet-3if9</link>
      <guid>https://dev.to/nicolaskempf57/creez-vos-cartes-interactives-avec-vue-js-et-leaflet-3if9</guid>
      <description>&lt;p&gt;Bonjour et bienvenue à tous sur ce tutoriel. Nous allons, au cours des prochains articles, apprendre ensemble à créer un site web permettant l’affichage d’une carte de nos restaurants favoris, le tout grâce au framework Vue.js et à Leaflet.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction et Setup
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Vue.js
&lt;/h2&gt;

&lt;p&gt;Comme dit précédemment, nous allons utiliser Vue.js. Si vous ne le connaissez pas, il s’agit d’un framework Javascript open-source très populaire, qui tient la dragée à Angular et React. Je vous invite à aller vous renseigner dessus à cette adresse: &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;https://vuejs.org/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Leaflet
&lt;/h2&gt;

&lt;p&gt;Leaflet est une librairie Javascript permettant de créer des cartes interactives et customisables. Librairie très populaire, facile à utiliser, elle sera au centre de ce tutoriel. Il existe une version spécifique pour Vue.js: &lt;a href="https://vue2-leaflet.netlify.app/" rel="noopener noreferrer"&gt;https://vue2-leaflet.netlify.app/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Générer le projet
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g @cli/vue
vue create npmduprojet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pour lancer le projet, on utilisera la commande:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Création de notre premier composant
&lt;/h1&gt;

&lt;p&gt;Rendez vous tout d’abord dans le projet généré, et allez dans le dossier src/components et créez un nouveau fichier Vue. Appelons le map.vue&lt;br&gt;
On le bind alors dans src/App.vue (cf exemple), avant de nous attaquer à remplir ce fichier map.vue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
 &amp;lt;div id="app"&amp;gt;
   &amp;lt;Map/&amp;gt;
 &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import Map from './components/map.vue'

export default {
 name: 'App',
 components: {
   Map
 }
}
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A partir de ceci, on va alors se demander ce que l’on veut voir s’afficher: Une carte bien sûr, puis des icônes s’affichant dessus à des coordonnées précises et chacune ayant son design propre ou ses propres informations lorsqu’on clique dessus… Commençons donc par afficher la carte.&lt;/p&gt;

&lt;p&gt;Pour cela, nous allons donc utiliser Leaflet, qui va nous servir donc à effectuer le rendu d’une carte dans notre application. Les choses étant bien faites, il existe une version de Leaflet spécialement pour Vue.js: Vue2Leaflet. Nous allons donc installer via npm les librairies nécessaires. A vos lignes de commandes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save leaflet
npm install --save vue2-leaflet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Il est très important d’installer Leaflet car il ne sera pas installé automatiquement lors de l’installation de vue2-leaflet. On s’exposerait alors à des troubles de fonctionnement assez évitables.&lt;br&gt;
Voici les 3 éléments que nous allons utiliser et leur fonctionnement:&lt;br&gt;
l-map: Le composant de base, contient tous les autres éléments et permet de gérer les principaux paramètres. &lt;br&gt;
l-tile-layer: Contient l’url de la map, ainsi que des options telles que le niveau de zoom ou la position par défaut.&lt;br&gt;
l-marker: Composant contenant les marqueurs qui apparaitront sur la map. Dans notre cas, le marker contiendra les icones des restaurants.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
 &amp;lt;l-map
   :center="center"
   :zoom="zoom"
   class="map"
   ref="map"
   @update:zoom="zoomUpdated"
   @update:center="centerUpdated"
 &amp;gt;
   &amp;lt;l-tile-layer
     :url="url"
   &amp;gt;
   &amp;lt;/l-tile-layer&amp;gt;
   &amp;lt;/l-map&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { LMap, LTileLayer } from 'vue2-leaflet';
import 'leaflet/dist/leaflet.css';

export default {
 components: {
   LMap,
   LTileLayer
 },
 data () {
   return {
     url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
     center: [ 49.1193089, 6.1757156 ],
     zoom: 12,
   }
 },
 methods: {
   zoomUpdated (zoom) {
     this.zoom = zoom;
     console.log(this.markers)
   },
   centerUpdated (center) {
     this.center = center;
   }
 }
}
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
 .map {
   position: absolute;
   width: 100%;
   height: 100%;
   overflow :hidden
 }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dans cet exemple, on voit ainsi la configuration “de base” permettant l’affichage de la carte dans notre navigateur, sans ajouts de marqueurs.&lt;br&gt;
Nous allons maintenant ajouter ce qui rendra notre carte unique: les l-marker. Comme expliqué plus haut, Ils seront placés sur la carte à des points précis afin, comme leur nom indique de marquer un emplacement. On les place juste après le l-tile-layer Voici ci dessous le code associé au design:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;l-marker
 :key="marker.id"
 :lat-lng="marker.coordinates"
&amp;gt;
&amp;lt;/l-marker&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On rajoute également dans data():&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;markers: [
   {id: 1, coordinates: [ 49.114910, 6.178810 ]},
   {id: 2, coordinates: [ 49.133290, 6.154370 ]},
   {id: 3, coordinates: [ 49.102160, 6.158850 ]},
   {id: 4, coordinates: [ 49.136010, 6.199630 ]},
   {id: 5, coordinates: [ 49.105563, 6.182234 ]},
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comme on le voit, tout fonctionne et les marqueurs sont présents.&lt;br&gt;
Satisfaits? Non? Il est vrai que le design de base laisse clairement à désirer. Heureusement, il est possible de le changer et de customiser les icônes de ces marqueurs afin qu’ils soient plus adaptés à ce qu’on veut leur faire montrer. Il est pour cela possible de créer une icône personnalisée. Afin de rendre notre code lisible et de pouvoir réutiliser ce qui sera l'icône de nos restaurants, nous allons créer un composant à part qui contiendra la future icône:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
 &amp;lt;l-marker
   :key="marker.id"
   :lat-lng="marker.coordinates"
 &amp;gt;
   &amp;lt;l-icon ref="icon"&amp;gt;
     &amp;lt;img class="restaurant-icon" :src="marker.imageUrl"/&amp;gt;
   &amp;lt;/l-icon&amp;gt;
 &amp;lt;/l-marker&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { LIcon, LMarker } from 'vue2-leaflet'
export default {
 components: { LIcon, LMarker },
 props: {
   marker: {
     type: Object,
     required: true
   }
 }
}

&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
 .restaurant-icon {
   height: 50px;
   width: auto;
 }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ne pas oublier de l’appeler à la place du l-maker dans map.vue&lt;br&gt;
On note la présence de l-icon: Ce composant permet de construire un composant Vue qui sera utilisé pour créer l'icône: Permet interactivité / code propre, voir de construire des icônes complexes (Plusieurs images qui se chevauchent, dynamisme). On peut également faire l’inverse et mettre le composant dans le l-icon afin de pouvoir réutiliser l’image icône dans un autre contexte, tout dépend des choix de développement. Dans le l-icon est précisée l'image qui lui sera associée, qu'on a définie dans les markers mis à jour:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;markers: [
        {id: 1, imageUrl: 'https://img.icons8.com/doodle/48/000000/fish-food--v1.png', coordinates: [ 49.114910, 6.178810 ]},
        {id: 2, imageUrl: 'https://img.icons8.com/doodle/48/000000/pizza--v1.png' ,coordinates: [ 49.133290, 6.154370 ]},
        {id: 3, imageUrl: 'https://img.icons8.com/doodle/48/000000/croissant--v1.png', coordinates: [ 49.102160, 6.158850 ]},
        {id: 4, imageUrl: 'https://img.icons8.com/doodle/48/000000/the-toast--v2.png', coordinates: [ 49.136010, 6.199630 ]},
        {id: 5, imageUrl: 'https://img.icons8.com/doodle/48/000000/hamburger.png', coordinates: [ 49.105563, 6.182234 ]},
      ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et voici donc le design de notre application:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs0ut6u60vbfon82g2wp3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs0ut6u60vbfon82g2wp3.png" alt="La catographie Leaflet avec nos icones personnalisés"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vous pouvez retrouver l'intégralité du code de ce projet ici: &lt;a href="https://github.com/Jorek57/VueLeaflet-Tutorial/tree/basic-map" rel="noopener noreferrer"&gt;https://github.com/Jorek57/VueLeaflet-Tutorial/tree/basic-map&lt;/a&gt;&lt;br&gt;
Dans une seconde partie, nous apprendrons à créer des clusters d’icône, et à améliorer l’UX de notre carte!&lt;/p&gt;

</description>
      <category>vue</category>
      <category>leaflet</category>
      <category>french</category>
    </item>
    <item>
      <title>De Laravel 5.5 à Laravel 8, j'ai manqué quoi?</title>
      <dc:creator>Nicolas KEMPF</dc:creator>
      <pubDate>Tue, 22 Dec 2020 10:33:15 +0000</pubDate>
      <link>https://dev.to/nicolaskempf57/de-laravel-5-5-a-laravel-8-j-ai-manque-quoi-15l0</link>
      <guid>https://dev.to/nicolaskempf57/de-laravel-5-5-a-laravel-8-j-ai-manque-quoi-15l0</guid>
      <description>&lt;p&gt;Suite à un projet client démarré en 2018 poursuivi sans montée de version, j'ai l'habitude de Laravel 5.5 et j'ai assez peu suivi les mises à jour du framework.&lt;/p&gt;

&lt;p&gt;J'en profite pour faire un article avec les plus grandes nouveautés à ne pas manquer !&lt;/p&gt;

&lt;h2&gt;
  
  
  Changement de méthode de versionning
&lt;/h2&gt;

&lt;p&gt;Traditionnellement, Laravel utilise une version sous la forme paradigme.majeure.mineure. Comme Taylor est satisfait par le paradigme actuel, il n'y aura plus de modifications comme nous l'avons connu lors des passages de Laravel 4 vers Laravel 5. Il était donc tout naturel de laisser de côté cette information. Laravel suit maintenant une notation de semantic versioning classique : majeure.mineure.patch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classes pour les channels
&lt;/h2&gt;

&lt;p&gt;On a l'habitude d'utiliser un controller sous la forme de classe dans nos développements mais ce n'était pas encore possible pour les channels. C'est maintenant le cas !&lt;/p&gt;

&lt;h2&gt;
  
  
  Passage à Bootstrap 4 et transfert vers un package
&lt;/h2&gt;

&lt;p&gt;Il n'y a pas grand chose à dire de plus sur ce point, le framework suit les mises à jour de Bootstrap et a séparé le système d'inscription / connexion dans un package composer à part. Il existe au choix une version Vue ou React.&lt;/p&gt;

&lt;h2&gt;
  
  
  Laravel Nova
&lt;/h2&gt;

&lt;p&gt;Depuis Laravel 5.7, Nova est un dashboard d'administration créé pour Laravel et coûtant 99€ pour les développeurs individuels ou 199€ pour les agences. Cela permet de gagner un temps considérable lors du démarrage d'un projet compte tenu de l'omniprésence des panels d'administration.&lt;/p&gt;

&lt;p&gt;Il est possible de personnaliser Nova et d'y ajouter des nouvelles fonctionnalités mais le produit n'est pas prévu pour être intégralement modifié. Il ne conviendra pas forcément à un besoin avec un design à intégrer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Laravel Telescope
&lt;/h2&gt;

&lt;p&gt;Nouvel outil de debug présent dans l'écosystème Laravel, Telescope permet de lister les requêtes de cache, les commandes exécutées, les évènements, les exceptions, les jobs, les e-mails, les modifications de modèles, les requêtes SQL et même es tâches planifiées !&lt;/p&gt;

&lt;h2&gt;
  
  
  Laravel Vapor
&lt;/h2&gt;

&lt;p&gt;Nouveau produit créé par Taylor Otwell, il s'agit un système de déploiement de Laravel pour l'architecture serverless d'Amazon Lambda et l'interfacage avec les autres produits AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Laravel Sanctum
&lt;/h2&gt;

&lt;p&gt;Nouvel arrivant dans l'écosystème Laravel, Sanctum est un système d'authentification clef en main pour vos applications Webs et mobiles. C'est un bon compromis entre Laravel UI qui concerne uniquement les applications web avec une connexion par session et Laravel Passport qui est un serveur Oauth 2 à part entière.&lt;/p&gt;

&lt;h2&gt;
  
  
  CORS
&lt;/h2&gt;

&lt;p&gt;Grand absent des middlewares de Laravel jusqu'à présent, il est maintenant possible de configurer le support des requêtes Cross Origin !&lt;/p&gt;

&lt;h2&gt;
  
  
  Laravel Jetstream
&lt;/h2&gt;

&lt;p&gt;Encore un nouveau projet dans l'écosystème Laravel. C'est un template de démarrage tout en un avec connexion, inscription, vérification d'email, 2FA, session, Laravel Sanctum et même une gestion d'équipe optionnelle. C'est un produit réalisé avec Tailwind CSS et Blade / Livewire ou VueJS / Inertia.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>french</category>
    </item>
    <item>
      <title>Laravel Breeze, le nouveau starter officiel d'authentification avec Blade et Tailwind CSS</title>
      <dc:creator>Nicolas KEMPF</dc:creator>
      <pubDate>Wed, 11 Nov 2020 19:22:17 +0000</pubDate>
      <link>https://dev.to/nicolaskempf57/laravel-breeze-le-nouveau-starter-officiel-d-authentification-avec-blade-et-tailwind-css-23bd</link>
      <guid>https://dev.to/nicolaskempf57/laravel-breeze-le-nouveau-starter-officiel-d-authentification-avec-blade-et-tailwind-css-23bd</guid>
      <description>&lt;p&gt;Laravel Breeze est un package composer qui facilite le démarrage de nos projets en proposant un système d'authentification minimaliste qui utilise Blade et Tailwind CSS.&lt;/p&gt;

&lt;p&gt;C'est l’un des deux projets teasés depuis quelques temps sans trop d'informations par &lt;a href="https://twitter.com/taylorotwell?lang=fr"&gt;Taylor Otwell&lt;/a&gt; avec Laravel Sail. À la différence de ce dernier dont on ne sait toujours rien, l'information est tombée hier, le projet est officiellement disponible sur github : &lt;a href="https://github.com/laravel/breeze"&gt;https://github.com/laravel/breeze&lt;/a&gt; 🥳&lt;/p&gt;

&lt;h2&gt;
  
  
  Présentation de Laravel Breeze
&lt;/h2&gt;

&lt;p&gt;Le package fait suite aux nombreuses critiques reçues par Laravel 8 qui a été perçu comme trop compliqué à cause de &lt;a href="https://jetstream.laravel.com/1.x/introduction.html"&gt;Laravel Jetstream&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Laravel Breeze est un scaffold avec les routes, les controllers, les form requests, les views, le style et les tests.&lt;/p&gt;

&lt;p&gt;La grande nouveauté est que l'intégralité du package est publié dans votre code source. Il vous est donc possible de modifier tout ce qui concerne la logique, les vues et le style!&lt;/p&gt;

&lt;p&gt;Il utilise uniquement Blade et &lt;a href="https://tailwindcss.com/"&gt;Tailwind CSS&lt;/a&gt; ce qui en fait un choix parfait pour les personnes qui connaissent Laravel mais pas les autres technologies des scaffolds existants. Pour rappel, il existe déjà &lt;a href="https://github.com/laravel/ui"&gt;Laravel UI&lt;/a&gt; basé sur React ou VueJS et &lt;a href="https://jetstream.laravel.com/1.x/introduction.html"&gt;Laravel Jetstream&lt;/a&gt; qui utilise soit Blade + &lt;a href="https://laravel-livewire.com/"&gt;Livewire&lt;/a&gt; soit VueJS + &lt;a href="https://inertiajs.com/"&gt;InertiaJS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Très concrètement, qu’est-ce qu’il y a dans Laravel Breeze?
&lt;/h2&gt;

&lt;p&gt;Pour un package minimaliste, il est plutôt bien fourni ! Il contient un système complet de gestion d'utilisateurs avec l'inscription, la connexion, la récupération de mot de passe, la vérification d’email, la confirmation de mot de passe et la déconnexion.&lt;/p&gt;

&lt;p&gt;Il est actuellement disponible en v0.0.4. On manque encore d'une réelle timeline sur sa sortie stable en 1.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation du projet
&lt;/h2&gt;

&lt;p&gt;Dans un projet Laravel nouvellement créé, il est possible d'ajouter Breeze très simplement avec composer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel/breeze &lt;span class="nt"&gt;--dev&lt;/span&gt;
php artisan breeze:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quand le package sera disponible en version 1.0.0, il n'y aura plus besoin du flag --dev.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>french</category>
    </item>
    <item>
      <title>Laravel: les middlewares</title>
      <dc:creator>Nicolas KEMPF</dc:creator>
      <pubDate>Fri, 08 May 2020 12:58:04 +0000</pubDate>
      <link>https://dev.to/nicolaskempf57/laravel-les-middlewares-22b</link>
      <guid>https://dev.to/nicolaskempf57/laravel-les-middlewares-22b</guid>
      <description>&lt;p&gt;Aujourd’hui on va voir un élément clef de tous les projets web : les middlewares parfois appelés filters. Simples à comprendre pour les développeurs un peu aguerris, ils représentent une difficulté pour les débutants.&lt;/p&gt;

&lt;h2&gt;
  
  
  C’est quoi un middleware ?
&lt;/h2&gt;

&lt;p&gt;Pour faire simple, ce sont des fonctions qui permettent d’enrichir ou de vérifier une requête avant qu’elle arrive à votre controller. &lt;/p&gt;

&lt;p&gt;Plusieurs middlewares sont fournis de base avec Laravel comme &lt;code&gt;auth&lt;/code&gt; pour autoriser l'accès à la route seulement aux requêtes liées à un utilisateur connecté.&lt;/p&gt;

&lt;h2&gt;
  
  
  Middlewares par défaut
&lt;/h2&gt;

&lt;p&gt;Laravel inclut les middlewares suivant dans chaque nouveau projet Laravel :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authenticate : renvoie une 401 si la requête ne contient pas d'Authorization&lt;/li&gt;
&lt;li&gt;CheckForMaintenanceMode : Si l'application est en maintenance, vérifie si l'IP ou la requête est autorisée pour l'exécuter malgré la maintenance&lt;/li&gt;
&lt;li&gt;EncryptCookies : Encrypte les cookies&lt;/li&gt;
&lt;li&gt;RedirectIfAuthenticated : Redirige sur la route définie comme Home si la requête est un utilisateur connecté&lt;/li&gt;
&lt;li&gt;TrimStrings : Trim chaque champ du body de la requête&lt;/li&gt;
&lt;li&gt;TrustProxies : Liste des proxies qui envoie les requêtes à votre server&lt;/li&gt;
&lt;li&gt;VerifyCsrfToken : Vérifie le token Csrf fournit par la requête&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le framework lui même en contient de nombreux autres :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AuthenticateWithBasicAuth&lt;/li&gt;
&lt;li&gt;Authorize&lt;/li&gt;
&lt;li&gt;EnsureEmailsVerified&lt;/li&gt;
&lt;li&gt;RequiredPassword&lt;/li&gt;
&lt;li&gt;AddQueuedCookiesToResponse&lt;/li&gt;
&lt;li&gt;ConvertEmptyStringToNull&lt;/li&gt;
&lt;li&gt;TransformRequest&lt;/li&gt;
&lt;li&gt;ValidatePostSize&lt;/li&gt;
&lt;li&gt;CheckResponseForModifications&lt;/li&gt;
&lt;li&gt;FrameGuard&lt;/li&gt;
&lt;li&gt;SetCacheHeadersd&lt;/li&gt;
&lt;li&gt;SubstituteBindings&lt;/li&gt;
&lt;li&gt;Throttle requests&lt;/li&gt;
&lt;li&gt;ThrottleRequestsWithRedis&lt;/li&gt;
&lt;li&gt;ValidateSignature&lt;/li&gt;
&lt;li&gt;AuthenticateSession&lt;/li&gt;
&lt;li&gt;StartSession&lt;/li&gt;
&lt;li&gt;ShareErrorsFromSession&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Créer votre middleware
&lt;/h2&gt;

&lt;p&gt;Avec artisan, il est possible de créer votre propre middleware avec la commande :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:middleware CheckAge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Pour Lumen, il est possible de créer directement le fichier dans &lt;code&gt;app/Http/Middleware&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php
namespace App\Http\Middleware;
use Closure;
class CheckAge
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request-&amp;gt;age &amp;lt;= 200) {
            return redirect('home');
        }

        return $next($request);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Cette classe dispose d'une fonction &lt;code&gt;handle&lt;/code&gt; qui sera appelé par le framework quand vous allez utiliser votre middleware. Le plus important est l'appel au callback &lt;code&gt;next&lt;/code&gt; qui permet de continuer la requête.&lt;/p&gt;

&lt;p&gt;Il est possible d'ajouter des paramètres à la fonction &lt;code&gt;handle&lt;/code&gt; que vous pourrez définir quand vous l'appelerez.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;‌&lt;/code&gt;`‌&lt;br&gt;
&amp;lt;?php&lt;/p&gt;

&lt;p&gt;namespace App\Http\Middleware;&lt;/p&gt;

&lt;p&gt;use Closure;&lt;/p&gt;

&lt;p&gt;class CheckRole&lt;br&gt;
{&lt;br&gt;
    /**&lt;br&gt;
     * Handle the incoming request.&lt;br&gt;
     *&lt;br&gt;
     * &lt;a class="comment-mentioned-user" href="https://dev.to/param"&gt;@param&lt;/a&gt;
  \Illuminate\Http\Request  $request&lt;br&gt;
     * &lt;a class="comment-mentioned-user" href="https://dev.to/param"&gt;@param&lt;/a&gt;
  \Closure  $next&lt;br&gt;
     * &lt;a class="comment-mentioned-user" href="https://dev.to/param"&gt;@param&lt;/a&gt;
  string  $role&lt;br&gt;
     * @return mixed&lt;br&gt;
     */&lt;br&gt;
    public function handle($request, Closure $next, $role)&lt;br&gt;
    {&lt;br&gt;
        if (! $request-&amp;gt;user()-&amp;gt;hasRole($role)) {&lt;br&gt;
            // Redirect...&lt;br&gt;
        }&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    return $next($request);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
&lt;code&gt;&lt;/code&gt;‌`&lt;/p&gt;

&lt;p&gt;Une fois votre middleware créé, il ne nous reste plus qu'à l'enregistrer pour qu'il soit reconnu par Laravel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enregistrer votre middleware
&lt;/h2&gt;

&lt;p&gt;En fonction de votre besoin, il existe plusieurs manières d'enregistrer votre middleware :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pour toute votre application&lt;/li&gt;
&lt;li&gt;pour une seule route&lt;/li&gt;
&lt;li&gt;dans un groupe de middleware&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enregistrer un middleware pour toute votre application
&lt;/h3&gt;

&lt;p&gt;Pour qu'il se déclenche à chaque requête, il faut l'enregistrer dans l'attribut &lt;code&gt;$middleware&lt;/code&gt; dans le fichier &lt;code&gt;app/Http/Kernel.php&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enregistrer un middleware pour une seule route
&lt;/h3&gt;

&lt;p&gt;La liste des middlewares utilisable pour vos routes ou groupes de route se trouve dans l'attribut &lt;code&gt;$routeMiddleware&lt;/code&gt; de la classe &lt;code&gt;App\Http\Kernel&lt;/code&gt;. Elle prend la forme d'un tableau associatif où la clef est une chaîne qui va servir d'identifiant et la valeur est la classe de votre middleware.&lt;/p&gt;

&lt;p&gt;Ensuite on peut l'utiliser directement lorsqu'on enregistre nos routes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;‌&lt;/code&gt;&lt;code&gt;‌&lt;br&gt;
Route::get('admin/profile', "MonController@fonction")-&amp;gt;middleware('auth');&lt;br&gt;
&lt;/code&gt;&lt;code&gt;‌&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Il est possible d'utiliser le nom de la classe plutôt que la clé du tableau pour bénéficier de l'autocompletion.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;‌&lt;/code&gt;&lt;code&gt;‌&lt;br&gt;
Route::get('admin/profile', "MonController@fonction")-&amp;gt;middleware(CheckAge::class);&lt;br&gt;
&lt;/code&gt;&lt;code&gt;‌&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Il est également possible d'enregistrer plusieurs middlewares pour une même route.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;‌&lt;/code&gt;&lt;code&gt;‌&lt;br&gt;
Route::get('/', function () {})-&amp;gt;middleware('first', 'second');&lt;br&gt;
&lt;/code&gt;&lt;code&gt;‌&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Enfin, il est possible d'empêcher l'exécution d'un middleware d'un groupe pour une de ses routes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;‌&lt;/code&gt;`‌&lt;br&gt;
Route::middleware([CheckAge::class])-&amp;gt;group(function () {&lt;br&gt;
    Route::get('/', function () {});&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route::get('admin/profile', function () {})-&amp;gt;withoutMiddleware([CheckAge::class]);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;});&lt;br&gt;
&lt;code&gt;&lt;/code&gt;‌`&lt;/p&gt;

&lt;h3&gt;
  
  
  Enregistrer un middleware pour un groupe de requêtes
&lt;/h3&gt;

&lt;p&gt;Dans le cas de middlewares que vous allez utiliser ensemble, il est possible de créer un groupe de middlewares dans la propriété &lt;code&gt;$middlewareGroups&lt;/code&gt;. Il vous suffira ensuite d'appeler uniquement ce groupe pour appliquer tous ses middlewares.&lt;/p&gt;

&lt;p&gt;C'est ce que fait Laravel par défaut avec les groupes &lt;code&gt;web&lt;/code&gt; et &lt;code&gt;api&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;‌&lt;/code&gt;`‌&lt;br&gt;
/**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The application's route middleware groups.
*&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="comment-mentioned-user" href="https://dev.to/var"&gt;@var&lt;/a&gt;
 array&lt;br&gt;
*/&lt;br&gt;
protected $middlewareGroups = [&lt;br&gt;
'web' =&amp;gt; [&lt;br&gt;
    \App\Http\Middleware\EncryptCookies::class,&lt;br&gt;
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,&lt;br&gt;
    \Illuminate\Session\Middleware\StartSession::class,&lt;br&gt;
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,&lt;br&gt;
    \App\Http\Middleware\VerifyCsrfToken::class,&lt;br&gt;
    \Illuminate\Routing\Middleware\SubstituteBindings::class,&lt;br&gt;
],&lt;/p&gt;

&lt;p&gt;'api' =&amp;gt; [&lt;br&gt;
    'throttle:60,1',&lt;br&gt;
    'auth:api',&lt;br&gt;
],&lt;br&gt;
];&lt;br&gt;
&lt;code&gt;&lt;/code&gt;‌`&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Passer des arguments à votre middleware
&lt;/h3&gt;

&lt;p&gt;L'ensemble des arguments se passe à votre middleware avec un &lt;code&gt;:&lt;/code&gt; après l'identifiant du middleware. S'il y a plusieurs arguments, on les sépare par des &lt;code&gt;,&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;‌&lt;/code&gt;&lt;code&gt;‌&lt;br&gt;
Route::put('post/{id}', function ($id) {})-&amp;gt;middleware('role:editor');&lt;br&gt;
&lt;/code&gt;&lt;code&gt;‌&lt;/code&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>french</category>
    </item>
    <item>
      <title>Les revues de code</title>
      <dc:creator>Nicolas KEMPF</dc:creator>
      <pubDate>Thu, 30 Apr 2020 10:17:24 +0000</pubDate>
      <link>https://dev.to/nicolaskempf57/les-revues-de-code-2jkj</link>
      <guid>https://dev.to/nicolaskempf57/les-revues-de-code-2jkj</guid>
      <description>&lt;p&gt;Un outil pour améliorer la qualité de votre codebase.&lt;/p&gt;

&lt;p&gt;Une revue de code ou code review consiste à vérifier les ajouts et modifications afin d’améliorer la qualité générale du code. L’objectif est de faire des retours ou commentaires en rapport avec :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;la fonctionnalité implémentée : est-ce qu’elle respecte le cahier des charges ?&lt;/li&gt;
&lt;li&gt;des oublis : un élément à rajouter ou du code inutile à supprimer&lt;/li&gt;
&lt;li&gt;des choix techniques : conseils sur des alternatives, complexité du code, etc.&lt;/li&gt;
&lt;li&gt;des guidelines propres au projet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour les modifications purement visuelles comme les espaces, le nommage des variables ou le fameux, il est recommandé d’avoir des commentaires ou corrections automatiques avec des outils comme &lt;a href="https://github.com/squizlabs/PHP_CodeSniffer"&gt;phpcs&lt;/a&gt; ou &lt;a href="https://github.com/FriendsOfPHP/PHP-CS-Fixer"&gt;php-cs-fixer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RJjtUme5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/standards.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RJjtUme5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/standards.png" alt="l'importance d'utiliser un standard par xkcd"&gt;&lt;/a&gt;&lt;br&gt;
lien direct : &lt;a href="https://xkcd.com/927/"&gt;https://xkcd.com/927/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quand faire une revue de code ?
&lt;/h2&gt;

&lt;p&gt;La revue de code se fait la plupart du temps à la fin du développement d’une fonctionnalité ou d’un correctif mais peut se faire dès que le code est mis en commun. &lt;/p&gt;

&lt;p&gt;Les plateformes de versionning les plus connues intègrent directement des possibilités de revue de code. On retrouve cette fonction dans &lt;a href="https://github.com/"&gt;Github&lt;/a&gt;, &lt;a href="https://about.gitlab.com/"&gt;Gitlab&lt;/a&gt;, &lt;a href="https://bitbucket.org/"&gt;Bitbucket&lt;/a&gt;, &lt;a href="https://azure.microsoft.com/fr-fr/services/devops/repos/"&gt;Azure DevOps&lt;/a&gt;, &lt;a href="https://www.phacility.com/phabricator/"&gt;Phabricator&lt;/a&gt;. Dans le cas de systèmes ne le permettant pas, il existe des outils spécialisés comme &lt;a href="https://www.gerritcodereview.com/"&gt;gerrit&lt;/a&gt; qui s’intègrent directement à git.&lt;/p&gt;

&lt;p&gt;Pour plus d’informations sur le sujet, Google a mis en ligne un ensemble de documents concernant &lt;a href="https://google.github.io/eng-practices/review/reviewer/"&gt;les pratiques de leurs ingénieurs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qjkpuQX6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/code_quality.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qjkpuQX6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/code_quality.png" alt="Une revue de code par xkcd"&gt;&lt;/a&gt;&lt;br&gt;
lien direct : &lt;a href="https://xkcd.com/1513/"&gt;https://xkcd.com/1513/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  L’intérêt d’une checklist
&lt;/h2&gt;

&lt;p&gt;En fonction de votre équipe, vous allez vite remarquer que certaines erreurs vont souvent revenir. Il peut être intéressant dans ce cas de créer une checklist que chaque reviewer pourra utiliser pour s’assurer de ne rien oublier.&lt;/p&gt;

&lt;p&gt;Pour démarrer, je vous mets ci-dessous la &lt;a href="https://nyu-cds.github.io/effective-code-reviews/03-checklist/"&gt;checklist&lt;/a&gt; proposée par la New York University dans le cadre de son cours &lt;a href="https://nyu-cds.github.io/effective-code-reviews/"&gt;Effective Code Review&lt;/a&gt; et &lt;a href="https://software-carpentry.org/"&gt;Software Carpentry&lt;/a&gt;, des projets pour apprendre les bonnes pratiques de programmation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Général
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Est-ce que le code fonctionne? Est-ce qu’il effectue son fonctionnement attendu, la logique est correcte, etc.&lt;/li&gt;
&lt;li&gt;Est-ce que tout le code se comprend facilement?&lt;/li&gt;
&lt;li&gt;Est-ce qu’il correspond à vos conventions de code? Cela comprend généralement la position des accolades, les noms de fonction et de variable, la taille des lignes, l’indentation, le format et les commentaires.&lt;/li&gt;
&lt;li&gt;Est-ce qu’il y a du code redondant ou dupliqué?&lt;/li&gt;
&lt;li&gt;Le code est-il aussi modulaire que possible?&lt;/li&gt;
&lt;li&gt;Une variable globale peut-elle être remplacée?&lt;/li&gt;
&lt;li&gt;Y-a-t-il des lignes de codes commentées?&lt;/li&gt;
&lt;li&gt;Les boucles ont-elles une taille définie et une condition de fin correct?&lt;/li&gt;
&lt;li&gt;Est-ce que les noms utilisés sont parlant et informent du sens de la variable ou fonction?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Y-a-t-il des optimisations évidentes pour améliorer la performance?&lt;/li&gt;
&lt;li&gt;Est-ce qu’une partie du code peut être remplacé par une librairie ou une fonction du langage?&lt;/li&gt;
&lt;li&gt;Reste-t-il du code concernant les logs ou le debug à supprimer?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sécurité
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Est-ce que toutes les données d’entrées sont vérifiées et encodées? Au niveau de leur type, taille, format et portée&lt;/li&gt;
&lt;li&gt;Quand des utilitaires tiers sont utilisées, les retours d’erreurs sont-ils contrôlés?&lt;/li&gt;
&lt;li&gt;Les valeurs de sortie sont-elles vérifiées et encodées?&lt;/li&gt;
&lt;li&gt;Les valeurs incorrectes sont-elles gérées?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Y-a-t-il des commentaires et décrivent-ils les objectifs du code?&lt;/li&gt;
&lt;li&gt;Toutes les fonctions sont-elles commentées?&lt;/li&gt;
&lt;li&gt;Y-a-t-il des comportements inhabituels ou des cas limites décrits?&lt;/li&gt;
&lt;li&gt;Est-ce que l’usage et le fonctionnement des librairies tierces sont documentés?&lt;/li&gt;
&lt;li&gt;Est-ce que les structures de données et les unités de mesures sont expliquées?&lt;/li&gt;
&lt;li&gt;Y-a-t-il du code incomplet ? Si oui, doit-il être supprimé ou marqué avec un TODO ou un autre moyen?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tests
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Le code est-il testable ? Le code doit être structuré pour qu’il n’ajoute pas trop ou ne cache pas de dépendance, qu’il soit capable d’initialiser ses objets. Des frameworks de tests peuvent être utilisés, etc.&lt;/li&gt;
&lt;li&gt;Des tests existent et sont-ils compréhensibles?&lt;/li&gt;
&lt;li&gt;Est-ce que les tests unitaires vérifient réellement que le code effectue la fonctionnalité attendue?&lt;/li&gt;
&lt;li&gt;Est ce que du code de test peut être remplacé par une API existante?&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Publié sur &lt;a href="https://www.nicolaskempf.fr/les-revues-de-code/"&gt;https://www.nicolaskempf.fr/les-revues-de-code/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>french</category>
      <category>codereview</category>
    </item>
    <item>
      <title>Installer Ghost avec docker-compose</title>
      <dc:creator>Nicolas KEMPF</dc:creator>
      <pubDate>Sat, 28 Mar 2020 16:18:09 +0000</pubDate>
      <link>https://dev.to/nicolaskempf57/installer-ghost-40af</link>
      <guid>https://dev.to/nicolaskempf57/installer-ghost-40af</guid>
      <description>&lt;p&gt;Aujourd’hui nous allons voir comment lancer un nouveau blog avec Ghost sur un VPS disposant de docker-compose. Les instructions sont les mêmes peu importe l’OS, c’est tout l’intérêt de docker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration de docker-compose pour Ghost
&lt;/h2&gt;

&lt;p&gt;Créer un fichier docker-compose.yml avec le contenu suivant :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2.3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ghost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost:latest&lt;/span&gt;
        &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
        &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./config.production.json:/var/lib/ghost/config.production.json:z&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ghost:/var/lib/ghost/content&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
            &lt;span class="na"&gt;VIRTUAL_PROTO&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
            &lt;span class="na"&gt;VIRTUAL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nicolaskempf.fr&lt;/span&gt;
            &lt;span class="na"&gt;VIRTUAL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
            &lt;span class="na"&gt;LETSENCRYPT_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nicolaskempf.fr&lt;/span&gt;
            &lt;span class="na"&gt;LETSENCRYPT_EMAIL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;contact@nicolaskempf.fr&lt;/span&gt;
        &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
        &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;nginx-proxy&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
        &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql&lt;/span&gt;

    &lt;span class="na"&gt;mysql&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:5.7&lt;/span&gt;
        &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db:/var/lib/mysql&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ROOT_PASSWORD&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nicolas&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MY_PASSWORD&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
        &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
        &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nginx-proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;ghost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ghost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
    &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;J’utilise &lt;a href="https://github.com/nginx-proxy/nginx-proxy"&gt;nginx-proxy&lt;/a&gt; et &lt;a href="https://github.com/nginx-proxy/docker-letsencrypt-nginx-proxy-companion"&gt;letsencrypt-nginx-proxy-companion&lt;/a&gt; pour faire le lien entre mes containers et mes noms de domaines. &lt;/p&gt;

&lt;p&gt;Il est possible de faire fonctionner le blog sans proxy en ajustant un peu les propriétés :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2.3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ghost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost:latest&lt;/span&gt;
        &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
        &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./config.production.json:/var/lib/ghost/config.production.json:z&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ghost:/var/lib/ghost/content&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
        &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
        &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;nginx-proxy&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
        &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql&lt;/span&gt;

    &lt;span class="na"&gt;mysql&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:5.7&lt;/span&gt;
        &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db:/var/lib/mysql&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ROOT_PASSWORD&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nicolas&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MY_PASSWORD&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
        &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
        &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;
&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nginx-proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;ghost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghost&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ghost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
    &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuration du container ghost
&lt;/h2&gt;

&lt;p&gt;Pour Ghost, on fournir un fichier de configuration JSON avec les informations de la base de données.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://nicolaskempf.fr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2368&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"database"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"client"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mysql"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"connection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mysql"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nicolas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MY_PASSWORD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"database"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ghost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"charset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"utf8mb4"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'Nicolas KEMPF' &amp;lt;contact@nicolaskempf.fr&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
        &lt;/span&gt;&lt;span class="nl"&gt;"transport"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SMTP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"logger"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"secureConnection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"logging"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"transports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"stdout"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"process"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"systemd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"contentPath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/var/lib/ghost/content"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Si tout se passe bien, Ghost se lance et crée les tables nécessaires à son fonctionnement dans la db.&lt;/p&gt;

&lt;p&gt;Au niveau de MySQL, il n'y a rien à faire, les variables d'environnement suffisent. Il est possible que vous aillez des erreurs au démarrage des services, le temps que mysql accepte les connexions. Pour le résoudre, il faudra ajouter un endpoint à ghost pour ne pas démarrer le conteneur tant qu'il n'arrive pas à se connecter à la db.&lt;/p&gt;

&lt;p&gt;Si jamais vous rencontrez l'erreur suivante, il suffit de supprimer le volume db et recommencer :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ER_HOST_NOT_PRIVILEGED: Host '172.30.0.3' is not allowed to connect to this MySQL server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Une fois le démarrage terminé, votre site est accessible à l’url choisie. Il ne vous reste plus qu’à vous rendre sur &lt;code&gt;/ghost&lt;/code&gt; pour créer votre compte administrateur.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Article publié sur &lt;a href="https://www.nicolaskempf.fr/installer-ghost-avec-docker/"&gt;https://www.nicolaskempf.fr/installer-ghost-avec-docker/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>docker</category>
      <category>ghost</category>
      <category>french</category>
    </item>
  </channel>
</rss>
