OWL Performance : une infra Dockerisée pour un déploiement en toute facilité

Comme j'en parlais dans un précédent article, un ami m'a demandé de lui monter une infrastructure en ligne pour soutenir son activité de coach sportif indépendant. Voici comment je m'y suis pris !

OWL Performance : une infra Dockerisée pour un déploiement en toute facilité
Owl Performance, une infra Dockerisée

Comme j'en parlais dans un précédent article, un ami m'a demandé de lui monter une infrastructure en ligne pour soutenir son activité de coach sportif indépendant. Après une rapide mise au point avec lui, on a déterminé les besoins suivants :

  • Un site vitrine qui présente son activité, sa philosophie; ce site servira notamment au référencement et aura un contenu relativement statique.
  • Un blog pour écrire des articles, partager des programmes de sport, des conseils nutritionnels, etc. qui constituera la partie dynamique de l'infra.
  • Un formulaire de contact pour que les personnes intéressées puissent lui adresser des messages.

Si vous voulez y faire un tour, le site est disponible à cette adresse :

Site vitrine : https://owl-performance.fr
Blog: https://owl-performance.fr/blog/

Aurélien est un coach passionné et très qualifié. Si jamais vous avez pour projet de vous remettre au sport, ou de vous perfectionner, n'hésitez pas à le contacter !

Développement du site vitrine

Je voulais pouvoir proposer à Aurélien un site vitrine complètement personnalisable qui correspondait au mieux à son besoin.

J'aurais pu le diriger vers des factories du style Wix.com, ce qui aurait sans doute donné de bons résultats en un temps record. D'un autre côté, je me suis dit que c'était aussi l'occasion de décrasser mes compétences en HTML / CSS et de m'intéresser aux questions de SEO.

J'ai donc développé le site entièrement à la main, avec pour seul sucre syntaxique, le SASS, plus particulièrement la syntaxe SCSS. Mes années de développement en Angular m'ont trop formaté pour repasser sur du CSS vanilla. Je me suis également aidé d'un petit bootstraper HTML/SCSS/JS que j'avais développé il y a un moment, et que vous pouvez retrouver ici si vous le souhaitez.

Après le développement et le premier déploiement, j'ai utilisé cet outil pour mesurer le score SEO de mon travail, et obtenir un premier score de... 29%. Ouch !
Heureusement, l'outil propose bien des axes d'amélioration, et après avoir corrigé la plupart des points qui posaient problèmes, j'ai atteint un score de 78%, que je considère comme suffisant, puisque la plupart de la communication de mon ami se fera sur son Instagram.

Le blog

Pour le moteur de blog, j'ai utilisé Ghost, comme pour le blog que vous êtes entrain de lire. Je voulais qu'Aurélien dispose d'une interface d'administrateur intuitive et selon moi, dans ce domaine, Ghost joue dans la cour des grands.

Pour se démarquer, je lui ai conseillé d'investir dans un thème payant, en raccord avec le look & feel du site vitrine que j'étais en train de développer.

La mise en place du blog et sa configuration s'est directement faite sur l'infrastructure, après un déploiement express avec Docker et ce petit docker-compose.yml :

version: '3'
services:

  ghost:
    image: ghost:latest
    restart: always
    environment:
      url: https://owl-performance.fr/blog
    volumes:
      - /opt/ghost_content:/var/lib/ghost/content
    ports:
      - 82:2368
docker-compose.yml pour Ghost

S'il y a une seule chose à retenir de ce fichier, c'est la création du volume qui pointe sur /var/lib/ghost/content, le répertoire qui contient toute la configuration de Ghost, les articles écrits ainsi que les images postées. J'ai juste veillé à cron-er la sauvegarde du répertoire /opt/ghost_content sur la machine host pour éviter une pertes de données en cas de maladroite suppression du volume.

Le service d'envoi de mails

Comme je le disais, le site vitrine possède un formulaire de contact. Pour envoyer des mails via cette page, j'ai utilisé un serveur NodeJS avec Express et la librairie nodemailer. Mon ami possédait déjà une adresse professionnelle chez Gmail, alors j'ai utilisé ce compte comme émetteur et destinataire des message provenant du formulaire.

Voici quelques snippets du serveur pour que voyez à quel point la librairie nodemailer fait le café :

const transporter = nodemailer.createTransport({
    service: 'Gmail',
    auth: {
        user: GMAIL_ADDRESS,
        pass: GMAIL_APP_PASSWORD
    }
});

let mail = {
    from: fromName + ' <' + from + '>',
    replyTo: fromName + ' <' + from + '>',
    to: GMAIL_ADDRESS,
    subject: subject,
    text: text
};

const sendEmail = (mail) => {
    transporter.sendMail(mailOptions, function(err){
        if (err) {
            // gérez votre erreur ici
        } else {
            // gérez votre retour ici
        }
    });
}

Notez qu'ici, le GMAIL_APP_PASSWORD n'est pas le mot de passe du compte Gmail, mais un mot de passe d'application créé pour l'occasion. Cela permet de renforcer la sécurité du compte, car Aurélien peut révoquer ce mot de passe quand bon lui semble, sans perdre l'intégralité du compte associé.

Pour en savoir plus sur les mots de passe d'application Gmail, rendez-vous ici !

Un problème d'émetteur !

L'utilisation de Gmail n'est pas nécessairement la meilleure solution, et pour cause; afin que dans sa boite mail, mon ami reçoive des mails en provenance de la personne qui utilise le formulaire, je me disais que j'allais remplacer la valeur from par l'adresse email saisie par l'utilisateur. Que nenni !

Gmail empêche la surcharge de la valeur from, et si elle est différente du compte émetteur du mail, il la remplace automatiquement par cette dernière. La conséquence ? Dans sa boite, Aurélien voit tous les mails arrivant du site comme provenant de sa propre adresse :

Tous les mails reçus du site proviennent de l'adresse émettrice ("moi")...

Bon, c'est moche, mais ça fait l'affaire, surtout qu'on peut toujours renseigner le paramètre "replyTo", qui, lorsque renseigné avec l'adresse mail de l'utilisateur, permet quand même à mon ami de lui répondre en utilisant le bouton "Répondre" sur Gmail.

En cliquant sur "Répondre", le destinataire renseigné est bien celui qui a envoyé le message, ici "Jérémy Flusin".

Pour palier correctement à ce problème, il faudrait utiliser un autre fournisseur de mail, ou mieux, monter notre propre serveur SMTP.

Déploiement de l'infra avec Docker

Je voulais que l'infra soit complètement déployable en un rien de temps, et que le seul prérequis pour son déploiement soit d'avoir installé Docker et Docker-Compose. C'est le cas de tous mes serveurs, et ça me permet une grande flexibilité sur les déploiements.

Voici les différents containers à l'oeuvre sur l'infra :

5 containers avec un rôle dédié
  • nginx-front : C'est un container NGINX dont le rôle est de réceptionner les requêtes HTTP (port 80) et HTTPS (port 443) venant de l'extérieur pour les rediriger vers le bon container en fonction de l'URL. Ce container contient aussi le certificat HTTPS généré via Let's Encrypt et mis à jour automatiquement par le certbot (cf. plus bas).
  • nginx-static : c'est encore une fois un container NGINX, qui héberge les sources statiques du site vitrine. On aurait pu se passer de ce container et intégrer les sources directement dans le nginx-front, mais je considère qu'il est aussi intéressant de séparer les responsabilités de chaque services du mieux possible.
  • nginx-ghost : le container Ghost, le moteur de blog.
  • mail-sender : le container NodeJS gérant l'envoi de mail.
  • let's-encrypt certbot : ce container s'occupe de mettre à jour le certificat HTTPS contenu dans le nginx-front automatiquement, avant expiration. Les deux containers partagent un volume dans lequel se trouve le certificat. Pour mettre en place ce fonctionnement, j'ai suivi ce super tutoriel, que je recommande chaudement !

Le gros avantage, c'est que toute cette infra est configurée via un seul fichier docker-compose.yml, donc un vrai plaisir à maintenir et à déployer ! Si dans le futur, Aurélien décide pour une raison quelconque de changer d'hébergeur, j'aurais juste besoin d'une machine avec Docker pour déployer l'infra avec une simple commande.

Pour conclure

L'infra a été déployée début Septembre, et les retours sont très bons, ce qui n'est pas sans me ravir ! Aurélien a commencé à saisir des articles sur son blog et a été agréablement surpris par la facilité d'utilisation de Ghost.

De mon côté, je surveille l'évolution du référencement du domaine pour les différents mots-clés, mais la compétition dans le monde des coachs sportifs est rude. Il va falloir multiplier les partages sur les réseaux sociaux pour que le saint algorithme de Google nous fasse remonter dans les résultats.