Alpine in Docker: Advanced Optimization (Artikel 212)
Fortgeschrittene Techniken zur Minimierung von Alpine-basierten Docker-Images. Erfahren Sie alles über Multi-Stage Builds, das Entfernen von Build-Artefakten und die Reduzierung der Angriffsfläche.
# Alpine Docker Masterclass: Das 5MB-Image-Paradigma
TL;DR / Management Summary Ein einfaches
FROM alpineist erst der Anfang. Um echte Enterprise-Grade Images zu bauen, nutzen wir Multi-Stage Builds. Dabei trennen wir die Build-Umgebung (Compiler, Header, Caches) strikt von der Laufzeitumgebung. Das Ziel ist ein Image, das nur die Binärdatei und ihre minimalen Laufzeit-Abhängigkeiten enthält. Keine Shell, kein Paketmanager, kein Ballast.
# 1. Einführung & Architektur
Die Trennung von Kirche und Staat.
In der Produktion brauchen wir weder gcc noch git oder npm. Wir brauchen nur das Ergebnis des Build-Prozesses.
# Der Multi-Stage Prozess (Mermaid)
graph TD
subgraph "Stage 1: The Builder (Heavy)"
A[FROM alpine:latest] --> B[apk add build-base git]
B --> C[git clone & compile]
C --> D[Artifact: myapp.bin]
end
subgraph "Stage 2: The Runner (Minimal)"
E[FROM alpine:latest] --> F[COPY --from=builder myapp.bin]
F --> G[Execution: ./myapp.bin]
end
D --> F
# 2. Praxis: Multi-Stage Build für Go
Maximale Kompression.
Go ist ideal für Alpine, da es statisch gelinkte Binaries erzeugen kann.
# --- Stage 1: Build ---
FROM golang:1.21-alpine AS builder
RUN apk add --no-cache git
WORKDIR /src
COPY . .
# -ldflags="-s -w" entfernt Debug-Symbole (spart ~20% Größe)
RUN go build -ldflags="-s -w" -o /app/server ./main.go
# --- Stage 2: Final ---
FROM alpine:3.18
# Security: Zertifikate für HTTPS-Aufrufe hinzufügen
RUN apk add --no-cache ca-certificates
COPY /app/server /usr/local/bin/server
# Non-Root User
RUN adduser -D staticuser
USER staticuser
ENTRYPOINT ["/usr/local/bin/server"]
# 3. Die ‘No-Shell’ Strategie
Angriffsfläche auf Null reduzieren.
Wenn ein Angreifer eine Sicherheitslücke in Ihrer App ausnutzt, ist seine erste Handlung meist sh oder bash zu starten. Wenn diese Programme nicht im Image sind, wird der Angriff massiv erschwert.
# Static Binaries auf Scratch
Wenn Ihre Applikation keine C-Libraries braucht, können Sie sogar Alpine weglassen:
FROM scratch
COPY /app/server /server
ENTRYPOINT ["/server"]
- Vorteil: Image Größe < 10MB. Keine Shell, kein Paketmanager.
- Herausforderung: Debugging ist nur über Sidecars möglich (siehe Artikel 196).
# 4. Day-2 Operations: Image Audit
Wo verstecken sich die Bytes?
Nutzen Sie das Tool Dive, um zu sehen, was in jedem Layer passiert.
# Auf dem Admin-Rechner
dive my-alpine-app:latest
Achten Sie auf das Feld “Potential wasted space”. Alles über 1MB sollte untersucht werden.
# 5. Troubleshooting & “War Stories”
Wenn ‘zu klein’ nicht mehr läuft.
# Story 1: “Der fehlende User-Kontext”
Symptom: Die App startet im Container, bricht aber beim Zugriff auf ein Verzeichnis mit “Permission Denied” ab, obwohl chmod 777 (unsauber!) gesetzt wurde.
Ursache: Das Multi-Stage Build kopiert zwar das Binary, aber nicht die /etc/passwd. Wenn das Binary einen spezifischen User erwartet, findet es die UID nicht.
Lösung: Kopieren Sie die User-Informationen aus der Builder-Stage oder legen Sie den User in der Final-Stage explizit neu an.
# Story 2: “Timezone-Verwirrung”
Symptom: In den App-Logs stehen Zeiten in UTC, der Server sollte aber auf Berlin stehen.
Ursache: Alpine enthält standardmäßig keine Zeitzonendaten (tzdata).
Lösung: Installieren Sie das Paket und setzen Sie den Link:
RUN apk add --no-cache tzdata && cp /usr/share/zoneinfo/Europe/Berlin /etc/localtime.
# 6. Fazit & Empfehlung
- Standard: Nutzen Sie immer Multi-Stage Builds. Es ist die einzige professionelle Methode.
- Security: Entfernen Sie am Ende des Builds alle Tools (
apk del build-base), falls Sie kein Multi-Stage nutzen können. - Wahl: Alpine ist die Basis, aber das Multi-Stage-Konzept ist die eigentliche Magie für Minimal-Images.
# Anhang: Cheatsheet
| Aufgabe | Befehl / Option |
|---|---|
| Layer aufräumen | rm -rf /var/cache/apk/* |
| Binaries strippen | RUN strip --strip-all mybinary |
| Image Layer zählen | docker history <id> |
| Dateisystem-Check | docker run --rm <image> ls -R / |
| Healthcheck | HEALTHCHECK --interval=30s CMD curl -f http://... |
| Cache löschen (Global) | docker builder prune |