Wer hat sich noch nicht geärgert, dass Entwicklungsumgebungen sich nur noch langsam aufsetzen lassen? Oder Produktivumgebungen ständig ausrollen und Speicherplatz und Bandbreite verbraten? Und wenn ein Image dann noch mit docker pull/push bewegt wird, läuft auch noch http mit. Gute Nacht. Timeout. Zu allem Überflüss laden die zahlreichen Tools der schwerfälligen Images geradezu zum Angriff ein.

Seit Version 17.05 (Edge) kommt Docker mit dem Feature Multi-Stage-Build, das im Dockerfile zu Hause ist. Multi-Stage-Build verhindert die Definition mehrerer Stages innerhalb eines Dockerfiles. Also das Kopieren von Projektdateien von einer Stage zur nächsten. Und da nun in jeder Stage ein anderes Image als Basis dient, sind am Ende Abhängigkeiten zum Kompilieren/Bauen getrennt von den Abhängigkeiten zur Laufzeit. Feine Sache.

Was Ihr davon habt:

Stellt Euch ein einfaches Web-Projekt vor aus statischen Dateien, wie CSS-, JS-Dateien und einer Handvoll JGS. Zur Laufzeit braucht das nur einen Webserver, nginx oder Apache. Für CSS wird dann plötzlich aber auch noch ein Präprozessor fällig wie SASS und JavaScript setzt Ihr wegen der Komplexität mit einem zeitgenäßen SPA-Framework und/oder TypeScript um. Und schon ist auch NodeJS mit von der Partie, obwohl wir das zur Laufzeit gar nicht brauchen. Eure Dockerfiles und Images sind nun also mit Interpretern vollgestopft, die zur Laufzeit kein Mensch braucht.

„Ich hab da mal was vorbereitet“

Und zwar der Multi-Stage-Build eines Golang-Projektes. Denn die Abhängigkeiten zum Entwickeln der Applikation sind andere, als zur Laufzeit. Der fette Go-Interpreter (selbst als Alpine-Image noch 78 MB) wird nur zum Bauen gebraucht. Danach läuft die App alleine. Unser kleines Projekt ist ein einfacher HTTP-Server. Das Dockerfile sieht so aus:

 

# Stage: Build
FROM golang:1.8-alpine as build
COPY src /usr/src/app
RUN cd /usr/src/app && \
go build

# Stage: Run
FROM alpine:latest
WORKDIR /root/
COPY –from=build /usr/src/app/app .
RUN chmod +x app
CMD [„./app“]
EXPOSE 80

Was läuft?

Zuerst lädt Docker Hub das offizielle Golang-Image. Als Alias, das haben wir in der ersten FROM-Zeile befohlen mit as build. Der Name ist frei wählbar, er wird später wichtig. Danach wird der mein Source-Code ins Image kopiert und kompiliert mit go build. Fertig ist diese Datei: /usr/src/app/app.

Das zweite FROM leitet die zweite Stage ein, die mit Alpine-Linux ohne Go-Interpreter auskommt. Nun wechseln wir ins Arbeitsverzeichnisses. Hier kopieren wir aus der vorigen benannten Stage, die kompilierte Datei. Mit einem einfachen COPY-Befehl. Dieser enthält nicht nur Quell- und Zielpfad, sondern auch die Ergänzung –from=build erhält. Das zeigt auf die vorherige Stage, von wo die Quelldatei kommen.

Zum Schluss noch ein paar Tipps, wie Ihr die App zum Laufen bringt. Beim Dockerfile bleibt alles beim Alten, gebaut mit docker build. Am Ende habt Ihr ein Docker Image auf Alpine-Linux-Basis und einer App-Datei. Bei mir Summa Summarum 18 MB Image. Funktioniert das auch bei Skriptsprachen? Also z.B. PHP mit seiner großemn Laufzeitungebung? Ja. Git, Composer und Konsorten, die nur Abhängigkeiten zur Build-Zeit auflösen sind im Betrieb überflüssig. Aber eins nach dem anderen. Erst einmal mit Multi-Stage-Builds starten, bevor wirs uns schwer machen und auf große Werkzeuge komplett verzichten.

Sie planen digitales Wachstum? Wir beraten Sie.

 

Anrufen

+49 (0) 681 / 60 29 01 – 0

In Ihrer Nähe

Konrad-Zuse-Str. 13
66115 Saarbrücken
Deutschland

Rückruf anfordern

6 + 3 =