Der beste Grund, Multi-Stage-Docker-Bauten zu verwenden, ist nicht die Ästhetik. Es ist Disziplin.
Produktionsbilder sollten die Anwendung und die Laufzeitumgebung enthalten, die erforderlich ist, um sie auszuführen. Sie sollten nicht auch enthalten:
- Compiler
- Paketmanager-Cache
- Testwerkzeuge
- Quelldateien, die nur zur Build-Zeit nützlich sind
Multi-Stage-Bauten machen diese Trennung ausdrücklich.
Das Muster
Bauen in einer Phase, ausführen in einer anderen:
FROM node:22-bookworm AS build
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
RUN pnpm prune --prod
FROM node:22-alpine AS runtime
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/package.json ./package.json
USER node
CMD ["node", "dist/server.js"]
Das gibt Ihnen eine klare Grenze zwischen "was zum Bauen erforderlich ist" und "was zum Ausführen erforderlich ist."
Die Alpine-Warnung
Alpine kann ein gutes Laufzeitbild sein. Es ist jedoch nicht automatisch das richtige.
Sie müssen weiterhin über Folgendes nachdenken:
- native Abhängigkeiten
- libc-Kompatibilität
- Debugging-Bedarf
- Bildherkunft
Manchmal ist ein schlankes Debian-basiertes Bild der bessere operative Kompromiss. Das Prinzip besteht darin, weniger zu versenden, nicht ein bestimmtes Basisbild zu verehren.
Was Ihnen das bringt
Gut gemacht verbessern Multi-Stage-Bauten:
- Bildgröße
- Kaltstart- und Ladezeit
- Angriffsfläche
- Klarheit über Laufzeitabhängigkeiten
Deshalb sind sie wertvoll, auch wenn der Unterschied in der Bildgröße moderat ist.
Weiterführende Literatur