Au démarrage d’un nouveau projet, j’ai toujours à cœur de choisir une stack technique permettant de :
- Disposer d’un environnement de développement quasi iso-prod (pour limiter l’apparition de bugs surprises lors des déploiements)
- Avoir un process de déploiement léger (du genre copie d’un seul fichier suivi d’un restart de l’applicatif)
Docker a longtemps été ma solution privilégiée pour répondre à ce besoin, mais il faut avouer que pour des projets modestes (50% des projets en somme), ça revient parfois à tuer une mouche à l’aide d’un bazooka…
Si vous êtes prêt à développer votre projet en go, j’ai une alternative à vous proposer avec ces 2 nouveautés sorties il y a quelques mois:
- Le nouveau package
embed
(dans la version 1.16 de go) - Une version stable de sqlite réécrite en pure go
Le package embed
The new
embed
package provides access to files embedded in the program during compilation using the new//go:embed
directive.
Vous vous souvenez quand je parlais d’un déploiement léger ? Et bien c’est exactement ce que permet de faire ce package.
Un exemple étant toujours plus parlant, prenons le cas d’une webapp et de son répertoire static
contenant diverses ressources (scripts js, css, fonts, …).
Nous allons créer une variable static.Fs
qui permettra d’embarquer toute l’arborescence “static” dans notre exécutable (via le commentaire go:embed).
Il n’y a alors plus qu’à servir les fichiers de cette arborescence via une route dédiée.
// Création d'un router via https://github.com/gorilla/mux
rooter := mux.NewRouter()
// Création d'un handler dédié aux fichiers statiques que l'on "branche" sur le répertoire embarqué "static"
// NB: je n'ai pas géré la gestion du cache pour garder l'exemple concis
staticFileHandler := http.StripPrefix(
"/static",
http.FileServer(http.FS(static.Fs)),
)
router.PathPrefix("/static").Handler(staticFileHandler)
Après compilation, vous avez certes un exécutable qui peut être assez volumineux du fait qu’il embarque tous les fichiers “static”, mais qui se suffit à lui-même pour un déploiement en production.
Sqlite
La petite base de données embarquée, longtemps cantonnée à des usages orientés device (application android, IoT, …) commence à prendre du galon côté serveur:
Generally speaking, any site that gets fewer than 100K hits/day should work fine with SQLite. The 100K hits/day figure is a conservative estimate, not a hard upper bound. SQLite has been demonstrated to work with 10 times that amount of traffic.
Elle peut donc très bien se substituer à un postgres, un mysql ou un oracle pour certains usages (blog, intranet, prédominance des accès en lectures à la base de donnée, …) avec un avantage indéniable, celui d’être embarqué:
- Pas besoin de l’installer / la configurer sur votre serveur de prod/dev
- Vous utilisez la même version de sqlite en prod et en dev
- Vous mettez à jour votre base de données en mettant à jour votre application
Mais ce n’est pas tout! Quand je parle de sqlite, je parle de cette version: https://gitlab.com/cznic/sqlite.
Qu’a-t-elle de particulier ?
C’est une réécriture de la version C en Go, il n’est donc nullement besoin de passer par CGO pour l’intégrer à votre projet.
- Vous évitez ainsi les problèmes de compilation croisée qui pourraient se poser si vous souhaitez déployer sur différents OS/Architectures.
- Au lieu de chercher à avoir un environnement de dev quasi iso-prod, c’est ici la dépendance de l’exécutable généré à l’environnement que l’on réduit, le but visé étant le même (éviter les bugs de prod non reproductibles en dev).
Mise en pratique
Le moteur de blog qui vous permet de lire ces lignes, je viens de le créer en appliquant cette stack (d’où ce premier article), et c’est un vrai bonheur de
- Ne pas avoir à installer / mettre à jour sur le serveur de tomcat / jboss / jvm / node.js / apache / nginx / docker engine / kubernetes…, ni de postgres /mysql… pour le faire tourner
- Pouvoir le compiler pour pratiquement n’importe quel OS / Architecture (Raspberry PI, macOS Server, …)
- Le déployer simplement en recopiant l’exécutable et en le redémarrant