Optimierung von Python-Docker-Images: Größenreduzierung um 43–57%
Mehrstufige Builds und Python-Slim-Images können die Laufzeit-Image-Größe von 895 MB auf 508 MB (-43%) reduzieren. Die Build-Zeit nach Codeänderungen sinkt von 56 auf 16 Sekunden. Dies beschleunigt Kubernetes-Deployments, spart Speicherplatz und reduziert den Datenverkehr.
Die Optimierung adressiert Schlüsselprobleme: schnelles Pod-Scaling bei Traffic-Spitzen und reduzierte Benutzerlatenz. Abhängigkeiten werden mit Poetry verwaltet, und Tests laufen in der Builder-Stufe.
.dockerignore und Slim-Images
Schließen Sie Tests und unnötige Dateien über .dockerignore aus. Tests werden nur während der Build-Stufe benötigt.
Wechseln Sie zu python:3.13-slim-bookworm. Das vollständige Image fügt hunderte MB hinzu.
Deaktivieren Sie den pip/Poetry-Cache mit Flags:
- pip:
--no-cache-dir - Poetry:
poetry cache clear --all pypi
Mehrstufiger Build: Dockerfile-Aufschlüsselung
Die Builder-Stufe installiert Poetry, Abhängigkeiten und führt pytest aus. Die Laufzeit-Stufe kopiert nur site-packages, Binärdateien (gunicorn, uvicorn) und Code.
# Builder-Stufe
FROM python:3.13-slim-bookworm AS builder
ENV PYTHONUNBUFFERED=1 \
LANG=C.UTF-8 \
PYTHONDONTWRITEBYTECODE=1
RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
curl \
gcc \
libc-dev \
&& pip install --no-cache-dir 'poetry==2.3.2' \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /code
COPY pyproject.toml poetry.lock* ./
RUN poetry config virtualenvs.create false \
&& poetry install --no-root --no-dev --no-interaction --no-ansi \
&& poetry cache clear --all pypi --no-interaction || true \
&& rm -rf ~/.cache/pip
COPY . .
RUN pytest
# Laufzeit-Stufe
FROM python:3.13-slim-bookworm
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
LANG=C.UTF-8
WORKDIR /code
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY --from=builder /usr/local/bin/gunicorn /usr/local/bin/gunicorn
COPY --from=builder /usr/local/bin/uvicorn /usr/local/bin/uvicorn
COPY --from=builder /code /code
Grundlegende Optimierungsergebnisse:
| Metrik | Vorher | Nachher | Veränderung |
|---------|------|-------|-----------|
| Image-Größe, MB | 894,84 | 508 | -43% |
| Vollständige Build-Zeit, s | 58 | 315 | +443% |
| Build-Zeit nach Änderungen, s | 56 | 16 | -71% |
Der erste Build ist aufgrund der Builder-Layer langsamer, aber Caching beschleunigt Iterationen.
Fortgeschrittene Methoden: Chainguard und manuelle Analyse
Chainguard-Images
Chainguard schließt Shell, apt/apk aus und minimiert die Angriffsfläche. Keine CVEs in Basis-Images. Einsparungen: 50–150 MB.
Nachteile:
- Debugging ohne Shell
- Nur für den neuesten Tag kostenlos
- Bezahlversionen sind teuer
Geeignet für Hochsicherheitsprojekte.
Manuelle Analyse mit dive
Analysieren Sie Layer:
docker history --format "{{.CreatedBy}}: {{.Size}}" image:tag
docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive:latest image:tag
Konzentrieren Sie sich auf große Laufzeit-Layer. Verkleinern Sie Verzeichnisse (Shift+Space), entfernen Sie unnötige Bibliotheken. Erfordert Linux-Expertise, lohnt sich selten.
Extreme Optimierung: scratch
Laufzeit auf scratch – kopieren Sie nur benötigte libc. Größe sinkt auf 384 MB (-57% vom Original, -24% vom mehrstufigen Build).
Nachteile:
- Debugging unmöglich
- Neue Abhängigkeiten erfordern manuelle Bibliothekshinzufügung
- Debugging-Zeit: 1+ Stunde
Relevant für tausende Pods, Serverless (Knative, Fargate). Schwieriger in Python als in Go.
Größenvergleich:
- Ohne mehrstufigen Build: 894 → 384 MB (-57%)
- Mehrstufiger Build: 508 → 384 MB (-24%)
Optimierung der Build-Zeit
Kopieren Sie pyproject.toml/poetry.lock VOR dem Code:
- COPY pyproject.toml poetry.lock* ./
- RUN poetry install
- COPY . .
- RUN pytest
Der Abhängigkeits-Cache bleibt bei Codeänderungen erhalten. Beschleunigung: 58 → 14 s (x4).
Wichtige Erkenntnisse
- Mehrstufig + slim: -43% Größe, -71% Iterationszeit.
- .dockerignore + no-cache: schließt Tests und Cache von der Laufzeit aus.
- COPY-Reihenfolge: Abhängigkeiten separat vom Code gecached.
- Scratch: -57%, aber für extreme Fälle (tausende Pods).
- Chainguard/dive: für Sicherheit und Feinabstimmung.
— Editorial Team
Noch keine Kommentare.