Powrót do strony głównej

Optymalizacja Python Docker: -43-57% rozmiaru

Artykuł omawia optymalizację obrazów Docker Python: budowanie multi-stage zmniejsza rozmiar o 43%, scratch — o 57%. Przykłady Dockerfile, benchmarki, analiza dive. Nadaje się dla middle/senior-developerów.

Python Docker: rozmiar -57% od zera dzięki multi-stage
Advertisement 728x90

Optymalizacja obrazów Docker dla Python: redukcja rozmiaru o 43–57%

Wieloetapowe budowanie i obrazy slim Python pozwalają zmniejszyć rozmiar obrazu runtime z 895 MB do 508 MB (-43%). Czas budowania po zmianach kodu spada z 56 do 16 sekund. Przyspiesza to wdrożenia w Kubernetes, oszczędza przestrzeń dyskową i ruch sieciowy.

Optymalizacja rozwiązuje kluczowe problemy: szybkie uruchamianie podów przy skokach obciążenia, redukcję opóźnień dla użytkowników. Zależności zarządzane są przez Poetry, testy wykonywane na etapie budowania.

.dockerignore i obrazy slim

Wyklucz testy i niepotrzebne pliki przez .dockerignore. Testy są potrzebne tylko na etapie budowania.

Google AdInline article slot

Przejdź na python:3.13-slim-bookworm. Pełny obraz dodaje setki MB.

Wyłącz cache pip/Poetry flagami:

  • pip: --no-cache-dir
  • Poetry: poetry cache clear --all pypi

Wieloetapowe budowanie: analiza Dockerfile

Etap builder instaluje Poetry, zależności, uruchamia pytest. Etap runtime kopiuje tylko site-packages, pliki binarne (gunicorn, uvicorn) i kod.

Google AdInline article slot
# Etap builder
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

# Etap runtime
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

Wyniki podstawowej optymalizacji:

| Metryka | Przed | Po | Zmiana |

|---------|------|-------|-----------|

Google AdInline article slot

| Rozmiar obrazu, MB | 894.84 | 508 | -43% |

| Czas budowania od zera, s | 58 | 315 | +443% |

| Czas budowania po zmianach, s | 56 | 16 | -71% |

Pierwsze budowanie jest wolniejsze z powodu warstw builder, ale cache przyspiesza iteracje.

Zaawansowane metody: Chainguard i analiza ręczna

Obrazy Chainguard

Chainguard wyklucza shell, apt/apk, minimalizując powierzchnię ataku. Brak CVE w obrazach bazowych. Oszczędność: 50–150 MB.

Wady:

  • Debugowanie bez shell
  • Darmowy tylko tag latest
  • Płatne — drogie

Nadaje się do projektów high-security.

Analiza ręczna z dive

Analizuj warstwy:

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

Skup się na dużych warstwach w runtime. Zwijaj katalogi (Shift+Space), usuwaj niepotrzebne libs. Wymaga doświadczenia z Linux, rzadko się opłaca.

Optymalizacja ekstremalna: scratch

Runtime na scratch — kopiuj tylko wymagane libc. Rozmiar spada do 384 MB (-57% od początkowego, -24% od multi-stage).

Wady:

  • Debugowanie niemożliwe
  • Nowe deps wymagają ręcznego dodawania libs
  • Czas na debugowanie: 1+ godzina

Aktualne dla tysięcy podów, Serverless (Knative, Fargate). W Python trudniejsze niż w Go.

Porównanie rozmiarów:

  • Bez multi-stage: 894 → 384 MB (-57%)
  • Multi-stage: 508 → 384 MB (-24%)

Optymalizacja czasu budowania

Kopiuj pyproject.toml/poetry.lock PRZED kodem:

  • COPY pyproject.toml poetry.lock* ./
  • RUN poetry install
  • COPY . .
  • RUN pytest

Cache zależności jest zachowany przy zmianach kodu. Przyspieszenie: 58 → 14 s (x4).

Co jest ważne

  • Multi-stage + slim: -43% rozmiaru, -71% czasu iteracji.
  • .dockerignore + no-cache: wyklucza testy i cache z runtime.
  • Kolejność COPY: zależności cache'owane oddzielnie od kodu.
  • Scratch: -57%, ale dla ekstremalnych przypadków (tysiące podów).
  • Chainguard/dive: dla bezpieczeństwa i precyzyjnego dostrojenia.

— Editorial Team

Advertisement 728x90

Czytaj dalej