📜Dockerfile, Build-Cache und Multi-Stage
Jede Zeile eines Dockerfiles ist ein Build-Schritt. Dateisystem-Änderungen werden zu Schichten, alles andere zu Metadaten. Der Cache entscheidet, welche Schritte wirklich laufen müssen.
🧪Build-Cache-Labor
Der erste Build läuft mit leerem Cache. Ändere dann eine Datei im Build-Kontext oder eine Zeile im Dockerfile und baue erneut: Ab dem ersten geänderten Schritt ist der Cache ungültig – für alle folgenden Schritte derselben Stufe.
Erst nur package*.json kopieren und installieren, danach den Quellcode. Code-Änderungen treffen nur die letzten Schritte.
📜 Dockerfile (editierbar)
1
2
3
4
5
6
7
8
📁 Build-Kontext
- README.md
- go.mod
- go.sum
- main.go
- next.config.ts
- package-lock.json
- package.json
- public/favicon.svg
- src/app/page.tsx
- src/lib/logik.ts
🕘 Build-Verlauf
✅ Selten Geändertes nach oben
Erst package.json kopieren und Abhängigkeiten installieren, dann den Quellcode. Vergleiche die Beispiele „cache-freundlich“ und „ungünstige Reihenfolge“ nach einer Änderung an src/app/page.tsx.
💡 Wie entsteht der Schlüssel?
Aus dem Schlüssel des Vorgängers und dem Anweisungstext – bei COPY/ADD zusätzlich aus Prüfsummen der kopierten Dateien. RUN-Befehle werden nicht erneut ausgeführt, nur verglichen:
RUN apt-get update bleibt gecacht, auch wenn es neue Pakete gibt.⚠️ Multi-Stage
Nur die Ziel-Stufe wird zum Image. Compiler, Dev-Abhängigkeiten und Quellcode bleiben in den Build-Stufen zurück. BuildKit baut nicht benötigte Stufen gar nicht erst.
🚀ENTRYPOINT + CMD = Startbefehl
Wer wird PID 1 im Container? Das hängt davon ab, wie ENTRYPOINT, CMD und die Argumente von docker run zusammenspielen.
PID 1 → /docker-entrypoint.sh nginx -g "daemon off;"
CMD liefert die Standard-Argumente für ENTRYPOINT.
📚Die Anweisungen
| Anweisung | Ergebnis | Zweck | Beispiel |
|---|---|---|---|
| FROM | Schicht | Basis-Image bzw. Beginn einer neuen Stufe | FROM node:22-alpine AS build |
| RUN | Schicht | Befehl beim Bauen ausführen; das geänderte Dateisystem wird zur Schicht | RUN apk add --no-cache curl |
| COPY | Schicht | Dateien aus dem Build-Kontext oder einer anderen Stufe kopieren | COPY --from=build /app/dist ./dist |
| ADD | Schicht | wie COPY, kann zusätzlich URLs laden und lokale tar-Archive entpacken | ADD app.tar.gz /opt/ |
| WORKDIR | Schicht | Arbeitsverzeichnis setzen (wird bei Bedarf angelegt) | WORKDIR /app |
| ENV | Metadaten | Umgebungsvariable – im Build und zur Laufzeit | ENV NODE_ENV=production |
| ARG | Metadaten | Build-Variable, nur während des Builds (--build-arg) | ARG VERSION=1.0 |
| EXPOSE | Metadaten | Dokumentiert einen Port – veröffentlicht ihn nicht! | EXPOSE 3000 |
| USER | Metadaten | Benutzer für folgende RUN-Befehle und den Container-Prozess | USER nextjs |
| CMD | Metadaten | Standard-Befehl bzw. Standard-Argumente für ENTRYPOINT | CMD ["node", "server.js"] |
| ENTRYPOINT | Metadaten | Fester Startbefehl; CMD und docker-run-Argumente werden angehängt | ENTRYPOINT ["/docker-entrypoint.sh"] |
| HEALTHCHECK | Metadaten | Prüfbefehl, aus dem Docker den Status healthy/unhealthy ableitet | HEALTHCHECK CMD wget -q -O /dev/null http://127.0.0.1:3000/ |
| VOLUME | Metadaten | Markiert ein Verzeichnis als Volume (anonymes Volume beim Start) | VOLUME /var/lib/mysql |
| LABEL | Metadaten | Schlüssel-Wert-Metadaten | LABEL org.opencontainers.image.source="…" |
| STOPSIGNAL | Metadaten | Signal für docker stop (Standard SIGTERM) | STOPSIGNAL SIGQUIT |
| SHELL | Metadaten | Shell für die Shell-Form von RUN/CMD/ENTRYPOINT | SHELL ["/bin/bash", "-c"] |