Dans cet article
Cessez d’installer Go sur votre machine hôte. Aucune pollution du
GOPATH, plus de « ça marche sur ma machine » et aucune dérive de version. C’est exactement la méthode que nous avons appliquée pour réécrire les agents Java des rapports BigBlueButton Learning Analytics et pour développer l’agent Go sécurisé de Piler. Voici comment livrer des binaires statiques en utilisant uniquement Docker.
Par Ghazi Triki, RIADVICE
Le problème du « il suffit d’installer Go »
Lorsque nous gérions des agents Java pour les rapports BigBlueButton Learning Analytics, nous étions confrontés au classique « enfer des dépendances ». Passer à Go promettait la simplicité, à condition de ne pas reproduire les mêmes erreurs. Il nous fallait un processus de compilation aussi hermétique que les binaires qu’il produisait.
Toute équipe finit par se heurter aux mêmes obstacles :
- La dérive des versions. Ahmed utilise la 1.24, Omar la 1.26 et le serveur de production la 1.25. Une légère modification du compilateur casse la compilation, mais uniquement chez Ahmed.
- Des machines hôtes polluées.
GOPATH,GOMODCACHEet des outils installés globalement (staticcheck,gofumpt) qui diffèrent d’un poste de travail à l’autre. - Une intégration laborieuse. Un nouvel ingénieur passe sa première journée à se débattre avec des variables d’environnement et des chaînes d’outils C pour
cgo.
Chez RIADVICE, nous sommes attachés à la rigueur et à l’ordre. Nous voulions un processus de compilation à leur image : propre, prévisible et partagé.
La réponse habituelle est « utilisez Docker », mais la plupart des tutoriels se contentent de montrer comment construire une image de conteneur. Ils n’expliquent pas comment obtenir un simple binaire lié statiquement sur votre machine hôte, c’est-à-dire l’artefact dont vous avez réellement besoin pour un service systemd ou un déploiement en environnement isolé, sans jamais installer le compilateur Go en local.
docker run --rm -v "$(pwd):/app" -w /app golang:1.26.5-trixie \
go build -o dist/myapp ./cmd/myappL’image officielle golang fait office de compilateur. Vos sources sont montées dans /app. Le binaire est écrit dans dist/myapp sur votre machine hôte. Une fois la commande terminée, le conteneur est détruit (--rm), et votre machine reste aussi propre qu’auparavant.
Retour d’expérience : de BigBlueButton à Piler
Il ne s’agit pas d’une simple théorie. Nous avons appliqué cette méthode à deux projets critiques :
- Rapports BigBlueButton Learning Analytics : nous avons réécrit de lourds agents Java sous forme de binaires Go légers. La compilation dans Docker nous a permis de cibler exactement l’environnement Debian des serveurs BBB, sans avoir besoin de cet environnement sur nos ordinateurs portables.
- Agent Go de Piler : pour notre solution d’archivage des e-mails, nous avons développé un agent à la sécurité renforcée. Le processus de compilation devait être aussi sûr que le code. En épinglant le compilateur sur un SHA précis, nous avons garanti la traçabilité de chaque bit du binaire.
Pourquoi c’est mieux que d’installer Go
| Critère | go install sur l’hôte | docker run golang:... |
|---|---|---|
| Version de Go | La dernière que vous avez installée | Épinglée, identique pour tous |
| GOPATH / cache | Pollue ~/go | Couches de conteneur hermétiques |
| Chaîne d’outils cgo | Configuration de l’hôte requise | Fournie dans l’image officielle |
| Parité avec la CI | « Ça marche sur ma machine » | Image identique, binaire identique |
BINARY := mini-api
DIST := dist
# Version metadata derived from git
VERSION := $(shell tmp=$$(git describe --tags --always --dirty 2>/dev/null) && echo "$${tmp#v}" || echo dev)
COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)
BUILD_DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS := -X example.com/mini-api/internal/version.Version=$(VERSION) \
-X example.com/mini-api/internal/version.Commit=$(COMMIT) \
-X example.com/mini-api/internal/version.Branch=$(BRANCH) \
-X example.com/mini-api/internal/version.BuildDate=$(BUILD_DATE)
# Pinned toolchain image
GO_IMAGE := golang:1.26.5-trixie
# Run any command inside the Go toolchain container
define run_in_docker
docker run --rm -v "$(PWD):/app" -w /app $(GO_IMAGE)
endef
.PHONY: build test lint
build:
@mkdir -p $(DIST)
$(call run_in_docker) bash -c 'CGO_ENABLED=0 go build -buildvcs=false -ldflags="$(LDFLAGS)" -o $(DIST)/$(BINARY) ./cmd/$(BINARY)'
@echo "Built $(DIST)/$(BINARY) (version $(VERSION))"
test:
$(call run_in_docker) go test -race ./...
lint:
$(call run_in_docker) go vet ./...Le Makefile, garant de la rigueur
Nous utilisons un Makefile pour formaliser les étapes de compilation. Notez que GO_IMAGE est épinglée sur une version précise. Nous n’utilisons jamais latest.
Les détails techniques qui comptent
1. CGO_ENABLED=0 pour des binaires statiques
Pour l’agent Piler, il nous fallait des binaires capables de fonctionner sur n’importe quel système, d’une Debian récente à un serveur ancien. Désactiver CGO garantit que le binaire contient tout ce dont il a besoin, sans aucune dépendance dynamique vis-à-vis des bibliothèques de l’hôte.
2. -ldflags -X pour la traçabilité
Votre binaire doit pouvoir indiquer précisément d’où il provient. Nous injectons le commit git et la date de compilation au moment de l’édition de liens. Cela s’est révélé essentiel pour déboguer les agents BigBlueButton sur des dizaines de clusters différents.
3. Épingler l’image du compilateur
Notre culture repose sur la cohérence. Épingler golang:1.26.5-trixie plutôt que d’utiliser latest signifie que si Ahmed compile le binaire aujourd’hui et Omar dans six mois, le résultat est identique au bit près.
Conclusion
Le compilateur est un outil et, comme tout outil, il doit rester à sa place. En déplaçant la chaîne d’outils Go dans Docker, nous avons éliminé toute une catégorie de bogues du type « chez moi, ça marche » et simplifié l’intégration de chaque nouvel ingénieur qui rejoint RIADVICE.
Que vous réécriviez des agents Java ou que vous développiez une API sécurisée pour Piler, cette méthode apporte la rigueur et la fiabilité qu’exigent les systèmes de production.
Ghazi Triki est le fondateur de RIADVICE. Nous concevons des intégrations sécurisées et performantes pour BigBlueButton, Piler et bien d’autres : construisons ensemble quelque chose de remarquable.





