5.3 KiB
Docker Build Stages
Das Dockerfile definiert drei Build-Stages für unterschiedliche Deployment-Szenarien.
Stages Übersicht
1. builder
Zweck: Baut sowohl Client als auch Server-Artefakte
Verwendung: Wird als Basis für production
Stage verwendet
Prozess:
- Installiert alle Dependencies (inkl. devDependencies)
- Baut Client mit Vite (
dist/
) - Baut Server mit TypeScript (
server-dist/
) - Kompiliert native Module (bcrypt) für Alpine Linux
2. production
Zweck: Vollständiger Build für Remote-Deployment (CI/CD, Production-Server)
Verwendung:
# docker-compose-prod.yml
build:
context: .
target: production
Prozess:
- Kopiert Source-Code (Client + Server) in Container
- Baut Client mit Vite (
dist/
) - Baut Server mit TypeScript (
server-dist/
) - Installiert nur Production-Dependencies
- Kompiliert native Module (bcrypt) für Alpine Linux
- Verifiziert bcrypt Installation
Vorteile:
- ✅ Vollständig autark (keine lokalen Builds nötig)
- ✅ Reproduzierbare Builds
- ✅ Ideal für CI/CD-Pipelines
Nachteile:
- ⏱️ Längere Build-Zeit (Client + Server werden im Container gebaut)
3. production-prebuilt
Zweck: Schnelles lokales Testing mit vorgebauten Artefakten
Verwendung:
# docker-compose.yml (lokal)
build:
context: .
target: production-prebuilt
Voraussetzungen:
dist/
undserver-dist/
müssen bereits existieren.dockerignore
darf diese Verzeichnisse NICHT ausschließen- Lokal ausführen:
pnpm run build
vordocker compose build/up
Prozess:
- Kopiert vorgebaute
dist/
undserver-dist/
aus Build-Context - Installiert nur Production-Dependencies
- Kompiliert native Module (bcrypt) für Alpine Linux
- Verifiziert bcrypt Installation
- Bei Fehlern schlägt der Build fehl
Vorteile:
- ⚡ Sehr schnelle Container-Builds (kein TypeScript/Vite-Build)
- 🔄 Ideal für lokale Entwicklung und Testing
Nachteile:
- ❌ Benötigt lokale Builds vor Docker-Build
- ❌ Nicht geeignet für Remote-Deployment
Verwendungsempfehlungen
Lokale Entwicklung
# 1. Baue Artefakte lokal (Client + Server)
pnpm install --frozen-lockfile
pnpm run build # erzeugt dist/ und server-dist/
# 2. Baue & starte Container mit production-prebuilt
docker compose build
docker compose up -d
Production-Deployment
# Nutzt production Stage (baut alles im Container)
docker-compose -f docker-compose-prod.yml up --build
CI/CD-Pipeline
# Explizit production Stage verwenden
docker build --target production -t myapp:latest .
Troubleshooting
Problem: "Cannot find module 'bcrypt'"
Ursache: Native Module (bcrypt) nicht korrekt für Alpine Linux kompiliert.
Lösung: Der Build schlägt jetzt absichtlich fehl, wenn bcrypt
nicht kompiliert werden kann. Prüfe die Build-Logs und stelle sicher, dass Build-Tools (python3, make, g++) installiert sind. Im production-prebuilt
-Szenario erfolgt ein Rebuild beim Container-Start.
Problem: "dist/ not found" im production-prebuilt Stage
Ursache: Lokale Builds fehlen
Lösung: Führe pnpm build
vor docker-compose up
aus
Problem: Container startet nicht in Production
Ursache: docker-compose-prod.yml nutzt falschen Stage
Lösung: Setze explizit target: production
in docker-compose-prod.yml
Native Module (bcrypt)
bcrypt ist ein natives Node.js-Modul, das für die jeweilige Plattform kompiliert werden muss.
Im Dockerfile (Build & Verifikation):
# Build-Dependencies für native Module
RUN apk add --no-cache python3 make g++ libc6-compat
# Nach pnpm install: bcrypt neu kompilieren (Fehler NICHT unterdrücken) und verifizieren
RUN echo "[production] Rebuilding bcrypt for Alpine Linux..." \
&& pnpm rebuild bcrypt --build-from-source \
&& echo "[production] Verifying bcrypt installation..." \
&& node -e "require('bcrypt')"
Im Startup (production-prebuilt):
Der Container verifiziert vor dem Start, dass bcrypt
verfügbar ist, und bricht mit klarer Fehlermeldung ab, falls nicht.
Troubleshooting: Native Module (bcrypt)
Problem: bcrypt_lib.node nicht gefunden
Symptom: Container startet mit Fehler:
Error: Cannot find module '/app/node_modules/.pnpm/bcrypt@5.1.1/node_modules/bcrypt/lib/binding/napi-v3/bcrypt_lib.node'
Ursache: Native Module wie bcrypt müssen für die Zielplattform (Alpine Linux) kompiliert werden. Wenn lokal auf Windows/Mac gebaut wird, sind die Bindings inkompatibel.
Lösung:
-
Für lokale Entwicklung (docker-compose.yml mit
production-prebuilt
):- Der Container rebuildet bcrypt automatisch beim Start
- Prüfe Logs:
docker compose logs stargirlnails | grep bcrypt
- Bei Fehlern:
docker compose down && docker compose build --no-cache
-
Für Production (docker-compose-prod.yml mit
production
):- bcrypt wird während des Docker-Builds kompiliert
- Build-Tools (python3, make, g++) sind im Image vorhanden
- Bei Fehlern: Prüfe Build-Logs auf Compiler-Fehler
-
Manuelle Verifikation:
docker compose exec stargirlnails node -e "require('bcrypt')"
Sollte ohne Fehler durchlaufen.
Best Practices
- Niemals
|| true
bei native Module Rebuilds verwenden - Immer Build-Tools im Production-Image behalten (python3, make, g++)
- Testen nach jedem Dependency-Update mit
--no-cache
Build