Présentation de notre starter-kit Docker

Chez JoliCode, la plupart de nos projets (clients ou internes) utilisent Docker, principalement pour simplifier l’expérience développeur en local. Quelques uns de nos gros projets ont une architecture suffisamment complexe pour justifier un autre fonctionnement (avec le binaire Symfony par exemple), mais pour tous les autres, l’infrastructure est souvent similaire : NGINX, PHP-FPM et une base de données (MariaDB ou PostgreSQL).

Pendant plusieurs années, nous avons copié/collé de projets en projets une infrastructure Docker gérée avec Fabric par dessus Docker Compose. Cette architecture a divergé au fil des projets jusqu’à ce que nous nous motivions enfin à centraliser cette configuration dans un repository externe :

https://github.com/jolicode/docker-starter

Introducing jolicode/docker-starter

Sous le capot

Ce projet, disponible en tant que template sur GitHub, fournit une architecture Docker parfaitement adaptée à nos projets les plus courants. Elle est configurée avec Docker Compose et utilise des images légères, pour une infrastructure rapide à installer et à démarrer.

De base, ce projet nous offre :

  • un serveur NGINX avec PHP-FPM ;
  • un serveur MariaDB ;
  • une image « builder » pour toutes les tâches et outils non nécessaires au runtime (Composer, Yarn, etc) ;
  • Traefik pour gérer les routing vers les conteneurs et avoir du HTTPS en local.

Fabric à la rescousse

Ce projet met à disposition une série de tâches Fabric permettant de simplifier l’interaction avec les conteneurs Docker. Par exemple :

Installer / démarrer la stack :

fab start

Démarrer un conteneur pour y lancer Composer / Yarn / Webpack / whatever :

fab builder

Supprimer toute trace de l’infrastructure (pratique après avoir testé un projet) :

fab down

Certaines tâches étaient présentes sur tous nos projets. Nous les avons donc incluses dans ce starter kit et elles n’attendent qu’à être adaptées à votre projet. C’est le cas de migrate pour mettre à jour le schéma de la base de données ou encore cache_clear pour vider le cache de votre applicatif.

Lancer fab -l ou consulter le fichier fabfile.py pour une liste des tâches disponibles par défaut.

Configuration minimale = DX simplifiée

Après avoir réussi à centraliser l’architecture dans un repos externe, nous avons passé du temps à simplifier au maximum son utilisation. Cela fait maintenant plusieurs mois que nous l’utilisons telle quelle dans nos projets.

Grâce à la surcouche Python (avec Fabric), seules 3 variables sont à configurer, une fois pour toute, pour chaque projet :

  • env.project_name: Sert à préfixer correctement tous les objets Docker (image, conteneur, volume, etc) ;
  • env.project_directory: Chemin du répertoire contenant l’application (utilisé pour le montage des volumes notamment) ;
  • env.project_hostnames : la liste des noms de domaines auxquelles doit répondre l’application en local.

HTTPS en local

Par défaut, la stack fonctionne en HTTPS grâce à un certificat auto-signé. Si votre projet requiert un certificat valide (certains outils refusent les certificats invalides), nous ne pouvons que vous recommander d’utiliser mkcert pour générer vos propres certificats.

Traefik est d’ailleurs configuré pour rediriger les requêtes HTTP en HTTPS.

Foire aux questions

Une FAQ valant mieux qu’un long discours, découvrez les réponses aux questions que vous ne vous étiez pas encore posé.

  • Est-ce que ce Starter Kit est compatible avec une application Symfony / Laravel / Whatever ?

Oui. Pour peu que votre application fournisse un dossier nommé public pour le web root, votre application marchera out of the box (c’est le cas de Symfony et Laravel). Si ce n’est pas le cas, il faudra probablement adapter légèrement le virtualhost de NGINX.

  • Pourquoi MariaDB au lieu de PostgreSQL ?

Au grand désespoir de Grégoire, la plupart de nos projets sont encore sur MariaDB. Le jour où la situation changera, nous appliquerons probablement le changement dans notre starter. En attendant, c’est assez simple de changer la base de données dans la configuration de docker-compose et le Dockerfile associé.

  • Est-ce que cette infrastructure est testée ?

Oui 😎. CircleCI est configuré pour s’assurer que la stack démarre correctement et que NGINX + PHP fonctionne. De plus, cette configuration fournit un exemple d’utilisation du docker_layer_caching ainsi que des workflows de Circle ✌.

  • C’est quoi cette surcouche Python, là ?

Docker Compose est un outil pratique pour gérer une application avec plusieurs conteneurs. En revanche, lorsque nous devons lancer une commande à la main, ça devient vite l’enfer. Entre la configuration de Docker Compose, les variables d’environnements à passer (pour corriger, entre autre, les permissions), le nom du projet, etc, on se retrouve rapidement avec une commande à rallonge :

docker-compose -p offithings -f /home/loick/Work/my_project/infrastructure/orchestration/base.yml -f /home/loick/Work/my_project/infrastructure/orchestration/local.yml -f /home/loick/Work/my_project/infrastructure/orchestration/builder.yml build --build-arg PROJECT_NAME=my_project --build-arg USER_ID=1000

Et en bons développeurs, nous sommes fainéants. Et nous préférons largement écrire une commande toute simple à la place :

fab start
  • Pourquoi avoir release un énième squelette Docker ?

Parce que nous utilisons Docker en interne depuis de nombreuses années, et qu’à force de copier / coller cette infrastructure de projet, nous avons préféré la centraliser pour simplifier le démarrage des nouveaux projets. Tout le monde n’est pas forcément à l’aise avec Docker et ce squelette nous permet donc de gagner du temps au démarrage d’un nouveau projet. Et quitte à avoir un squelette qui marche parfaitement pour nous, autant l’open-sourcer pour en faire profiter la communauté 😉. Personne n’est forcé de l’utiliser et nous n’avons clairement pas la prétention d’avoir la meilleure architecture. Elle correspond avant tout à nos besoins.

  • J’ai une idée de feature à ajouter, vous acceptez les Pull Requests ?

Comme expliqué ci-dessus, ce starter-kit correspond à nos méthodes de développement et n’a pas vocation à répondre à tous les besoins. Mais ça ne veut pas dire que nous ne sommes pas ouvert au dialogue et nous sommes preneur de toute bonne idée. N’hésitez pas à ouvrir un ticket pour en discuter 🙏.

blog comments powered by Disqus