3 Min. Lesezeit
Ein neuer Rechner braucht Docker und sonst nichts
Die Entwicklung läuft in einem Container
Teil acht des Boring Stack. Die App ist Go, und templ und Tailwind erzeugen Code und CSS. Das sind drei Toolchains, bevor man eine Zeile schreibt. Dieser Text handelt davon, wie ich sie von meinem Rechner fernhalte.
Jedes Projekt, das ich baue, hat einen einzigen unterstützten Weg, es in der Entwicklung zu starten:
task dev
Das führt docker compose up --build aus. Dann öffne ich die App im Browser und fange an.
Was im Container läuft
Das Entwicklungsimage enthält Go, Node (nur für das Tailwind-Kommandozeilenwerkzeug) und alles andere, was das Projekt braucht. Der Projektordner ist in den Container eingebunden, also bearbeite ich die Dateien auf meinem Rechner mit meinem gewohnten Editor.
Beim Start des Containers passiert Folgendes:
- Die npm-Abhängigkeiten werden installiert, falls sie fehlen.
- Das CSS wird einmal gebaut.
- Der Tailwind-Watcher startet im Hintergrund.
templ generate --watchläuft, erzeugt Go-Code neu, wenn sich ein Template ändert, startet den Server neu und lädt den Browser über einen kleinen Proxy neu.
Ein Template ändern, und die Seite lädt neu. Eine Go-Datei ändern, und der Server startet neu. Eine Klasse ändern, und das CSS wird neu gebaut.
Warum nur ein Weg
Es geht nicht um Docker. Es geht darum, dass es genau einen Weg gibt und dass er im Repository steht.
- Ein neuer Rechner ist in Minuten bereit. Docker installieren, klonen,
task dev. Kein Versionsmanager für Go, keiner für Node, kein «auf meinem Rechner läuft’s». - Die Versionen kommen aus dem Projekt. Die Go-Version ist in
go.modfixiert, die Werkzeuge mit Gostool-Direktive, und die npm-Pakete kommen aus der Lock-Datei. Die Versionen auf meinem Rechner spielen keine Rolle. - Ein Projekt, das ich ein Jahr nicht angefasst habe, startet immer noch. Der Container hat die Toolchain, die das Projekt erwartet, nicht die, auf die ich inzwischen aktualisiert habe.
Details, die zählen
- Caches in benannten Volumes. Die Modul- und Build-Caches von Go liegen in Docker-Volumes, überleben also
docker compose down, und der zweite Start ist schnell. node_modulesberührt den Host nie. Der Ordner enthält plattformspezifische Binaries. Ein Ordner, der im Container für Linux gebaut wurde, funktioniert auf macOS nicht und umgekehrt. Ein eigenes Volume hält ihn im Container.- Erzeugte Dateien sind eingecheckt. Der Go-Code, den templ erzeugt, liegt im Repository, also funktionieren
go buildundgo testauch direkt auf dem Host, falls Go dort installiert ist. Der Container ist der unterstützte Weg, nicht der einzig mögliche.
Überall dieselben Befehle
Ein Taskfile.yml enthält vier Tasks, identisch in allen meinen Projekten: dev, test, lint, down. Egal, welches Projekt ich öffne, die Befehle sind dieselben. Der Linter läuft in der CI, bevor irgendetwas gebaut wird, also stoppt ein Lint-Fehler einen Deploy.
Was es kostet
- Docker Desktop auf macOS braucht Arbeitsspeicher und Akku. Auf einem Laptop merkt man das.
- Das Beobachten von Dateien über einen eingebundenen Ordner ist langsamer als nativ. Bei der Grösse meiner Projekte ist das kein Problem.
- Eine Schicht mehr, wenn etwas kaputtgeht. Ab und zu lautet die Frage: «Ist es mein Code oder der Container?» Die Antwort ist fast immer mein Code.
Wann ich anders entscheiden würde
Für einen einzelnen kleinen Go-Service ohne Templates oder CSS reicht go run, und Docker wäre Overhead. Sobald eine zweite Toolchain dazukommt, zahlt sich der Container aus.
Als Nächstes: wo alles läuft.