Linuxguide

Docker Multi-Stage Builds – schlanke Production-Images 2025

Build-Artefakte von Runtime trennen – Images 10× kleiner

S
SeeColors IT
11. Juni 20264 Min. Lesezeit160 Aufrufe

Was sind Multi-Stage Builds?

Bei normalen Dockerfiles landet der gesamte Build-Kontext im finalen Image – Compiler, npm/node_modules, Quellcode, Test-Tools. Das macht Images unnötig groß und erhöht die Angriffsfläche.

Multi-Stage Builds lösen das: Sie definieren mehrere FROM-Stufen. Nur was Sie explizit kopieren landet im finalen Image.

Node.js Multi-Stage Build

# Stage 1: Dependencies installieren und bauen
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# Stage 2: Build (TypeScript kompilieren)
FROM builder AS compile
RUN npm ci
COPY tsconfig.json .
COPY src/ ./src/
RUN npm run build

# Stage 3: Finales Production-Image
FROM node:20-alpine AS production
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
# Nur node_modules (production) und dist/ kopieren
COPY --from=builder /app/node_modules ./node_modules
COPY --from=compile /app/dist ./dist
COPY package.json .
USER app
EXPOSE 3000
CMD ["node", "dist/server.js"]

Größenvergleich:

  • Ohne Multi-Stage: ~800 MB
  • Mit Multi-Stage: ~120 MB

Go Multi-Stage Build

Go ist prädestiniert für Multi-Stage – statisch gelinkte Binaries:

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o server .

# Finales Image: NUR die Binary!
FROM scratch
COPY --from=builder /app/server /server
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 8080
ENTRYPOINT ["/server"]

Image-Größe: ~10 MB (verglichen mit ~700 MB mit Standard-Go-Image)!

Java Spring Boot

FROM eclipse-temurin:21-jdk AS builder
WORKDIR /app
COPY mvnw pom.xml ./
COPY .mvn .mvn
RUN ./mvnw dependency:resolve -q
COPY src ./src
RUN ./mvnw package -DskipTests

# Layered JAR extrahieren (für besseren Cache)
RUN java -Djarmode=layertools -jar target/*.jar extract

FROM eclipse-temurin:21-jre AS production
WORKDIR /app
RUN addgroup --system app && adduser --system --group app
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./
USER app
EXPOSE 8080
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

Spezifische Stages bauen

# Nur bis zur "test" Stage bauen (CI-Pipeline)
docker build --target test -t myapp:test .

# Production Stage
docker build --target production -t myapp:latest .

Build-Cache optimal nutzen

# Dependencies ZUERST kopieren (ändert sich selten → Cache-Hit)
COPY package.json package-lock.json ./
RUN npm ci

# Quellcode DANACH (ändert sich oft → invalidiert Cache ab hier)
COPY src/ ./src/
RUN npm run build

BuildKit Build-Secrets

# Secret wird nicht im Image gespeichert!
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
    npm install @private/package
DOCKER_BUILDKIT=1 docker build \
  --secret id=npmrc,src=.npmrc \
  -t myapp:latest .

FAQ

Kann ich Stufen beliebig benennen?
Ja, mit AS stagename. Ohne Namen sind sie als 0, 1, 2 adressierbar.

Was passiert mit Zwischenstufen nach dem Build?
Sie bleiben im Build-Cache für schnellere Folge-Builds. Mit docker buildx prune werden sie bereinigt.

Fazit

Multi-Stage Builds sind Pflicht für Produktions-Images – kleinere Images, schnellere Deployments und bessere Sicherheit.

DevOps-Optimierungen für KMU in Heidelberg, Mannheim und der Rhein-Neckar-Region. Anfragen.

Artikel teilen

War dieser Artikel hilfreich?

Dein Feedback hilft uns, bessere Inhalte zu erstellen.

Kommentar hinterlassen

Verwandte Artikel