Django-Docker-Builds optimieren mit uv
Inhaltsverzeichnis
Wer in Docker-Containern Python-Abhängigkeiten mit pip
verwaltet, sollte einen Blick auf uv
von Astral werfen. Dieses Tool bietet deutlich schnellere Installationen und robustere Verwaltung der Abhängigkeiten. Besonders für Django-Projekte in der CI oder Produktion kann das Build-Tempo spürbar verbessert werden. Auch die Pflege und das Aktualisieren der Abhängigkeiten werden einfacher.
uv
im Dockerfile einbinden
Die empfohlene Methode nutzt ein Multi-Stage-Build, um das aktuelle uv
-Binary direkt ins Image zu kopieren:
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
So spart man sich die Installation via pip
oder Paketmanager und bleibt immer aktuell.
Wichtige Umgebungsvariablen
Im Dockerfile werden zentrale Umgebungsvariablen gesetzt:
ENV UV_PROJECT_ENVIRONMENT=/venv \ UV_NO_MANAGED_PYTHON=1 \ UV_PYTHON_DOWNLOADS=never \ VIRTUAL_ENV=/venv
UV_NO_MANAGED_PYTHON=1
:uv
verwaltet Python nicht selbst.UV_PYTHON_DOWNLOADS=never
: Downloads werden komplett deaktiviert.UV_PROJECT_ENVIRONMENT=/venv
: Virtuelle Umgebung wird unter/venv
verwaltet.
Performance-Verbesserungen
ENV UV_COMPILE_BYTECODE=1 \ UV_LINK_MODE=copy \ UV_CACHE_DIR=/app/.cache/uv
- Bytecode wird beim Installieren erzeugt (
.pyc
), schnellere Startzeit. - Hardlink-Probleme werden durch Kopieren vermieden.
- Caching via Docker-Mounts beschleunigt Builds enorm.
Sicherheit und Reproduzierbarkeit
ENV UV_FROZEN=1 \ UV_REQUIRE_HASHES=1 \ UV_VERIFY_HASHES=1
- Nur exakt definierte Versionen werden installiert.
- Jeder Download wird über einen kryptografischen Hash abgesichert.
Abhängigkeiten installieren
RUN uv venv $VIRTUAL_ENV RUN --mount=type=cache,target=/app/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ uv sync --no-install-project --no-editable
Diese Befehle installieren exakt die in der uv.lock
Datei festgelegten Pakete.
Dev- und Test-Abhängigkeiten verwalten
Mit dependency-groups
lassen sich verschiedene Umgebungen differenzieren:
[project] dependencies = ["django~=5.2"]
[dependency-groups]
dev = [“django-debug-toolbar”] test = [“pytest”]
[tool.uv]
default-groups = []
Mit Build-Argumenten lassen sich Gruppen gezielt installieren:
ARG BUILD_GROUPS="" RUN --mount=type=cache,target=/app/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ uv venv $VIRTUAL_ENV && \ uv sync --no-install-project --no-editable $BUILD_GROUPS
Beispielaufrufe:
# Nur Produktivabhängigkeiten $ docker build . # Mit Entwicklungswerkzeugen $ docker build --build-arg BUILD_GROUPS="--group dev" # Mit Testumgebung $ docker build --build-arg BUILD_GROUPS="--group test"
Migration von pip
Bestehende Projekte lassen sich überführen mit:
uv add --requirements requirements.txt uv add --group dev --requirements requirements-dev.txt uv lock
Pflege und Updates
Veraltete Pakete prüfen:
uv pip list --outdated
Lock-Datei aktualisieren:
uv lock --upgrade
Damit bleibt die Abhängigkeitsverwaltung reproduzierbar, sicher und wartbar.
Diese Methode spart Zeit, Bandbreite und sorgt für eine klar strukturierte und abgesicherte Docker-Infrastruktur für Python-Projekte wie Django. Wer auf schnelle CI/CD-Pipelines, reproduzierbare Builds und saubere Produktionsimages setzt, findet in uv
eine moderne und effiziente Lösung.
Hier das finale Dockerfile
### BUILD IMAGE ### FROM python:3.13-slim AS builder ENV DJANGO_SETTINGS_MODULE=myproj.settings \ PATH="/venv/bin:$PATH" \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ UV_CACHE_DIR=/root/.cache/uv \ UV_COMPILE_BYTECODE=1 \ UV_FROZEN=1 \ UV_LINK_MODE=copy \ UV_NO_MANAGED_PYTHON=1 \ UV_PROJECT_ENVIRONMENT=/venv \ UV_PYTHON_DOWNLOADS=never \ UV_REQUIRE_HASHES=1 \ UV_VERIFY_HASHES=1 \ VIRTUAL_ENV=/venv COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv RUN <<EOT apt-get update -y && \ apt-get install -y --no-install-recommends \ build-essential \ # other build dependencies here EOT WORKDIR /app ARG BUILD_GROUPS="" RUN --mount=type=cache,target=/app/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ uv venv $VIRTUAL_ENV && \ uv sync --no-install-project --no-editable $BUILD_GROUPS # Copy what's needed to run collectstatic. COPY myproj /app/myproj COPY media /app/media COPY manage.py /app/ RUN DEBUG=False ./manage.py collectstatic --noinput ### FINAL IMAGE ### FROM python:3.13-slim ARG PORT=8000 ENV DJANGO_SETTINGS_MODULE=myproj.settings \ PATH="/venv/bin:$PATH" \ PORT=${PORT} \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ VIRTUAL_ENV=/venv EXPOSE ${PORT} ENTRYPOINT ["/bin/bash", "/app/bin/run"] CMD ["prod"] WORKDIR /app RUN <<EOT apt-get clean -y && \ apt-get update -y && \ apt-get install -y --no-install-recommends \ # OS dependencies, e.g. bash, db clients, etc. bash && \ apt-get autoremove -y && \ apt-get clean -y && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* EOT # Copy selectively from builder to optimize final image. # --link enables better layer caching when base image changes COPY --link --from=builder /venv /venv COPY --link --from=builder /app/myproj /app/myproj COPY --link --from=builder /app/static /app/static COPY --link --from=builder /app/manage.py /app/manage.py
Leave a Reply