Developer Blog

Tipps und Tricks für Entwickler und IT-Interessierte

Recent Updates

Our latest news

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
Daily: How to transcribe Videos

Inhaltsverzeichnis

Using Commandline and Python

Option 1: Transcribe with Whisper (official)

pip install git+https://github.com/openai/whisper.git

Then run:

whisper demo.mp4 --model medium --language auto --output_format txt

Optional flags:

  • --output_format srt (for subtitles)
  • --language en (to skip language detection)

Create a shell script to transcribe multiple files

#!/usr/bin/env bash

# Loop through all arguments (filenames)
for VIDEO in "$@"; do
    echo "Transcribing: $VIDEO"
    whisper "$VIDEO" --model medium --language en --output_format txt
done

Option 2: Transcribe with faster-whisper (much faster on CPU or GPU)

pip install faster-whisper

Run via Python:

import sys
from faster_whisper import WhisperModel

VIDEO=sys.arg[1]

model = WhisperModel("medium", device="cpu")  # or "cuda" for GPU
segments, info = model.transcribe(VIDEO)

with open("transcript.txt", "w") as f:
    for s in segments:
        f.write(f"{s.start:.2f} --> {s.end:.2f}: {s.text.strip()}\n")

Optional: Convert to audio (if needed)

If transcription fails or is slow, extract audio first:

ffmpeg -i your_video.mp4 -ar 16000 -ac 1 -c:a pcm_s16le audio.wav

Then transcribe audio.wav instead.


Problems with numpy

Error when running whisper: A module that was compiled using NumPy 1.x cannot be run in NumPy 2.2.6 as it may crash.

Reason:

The error you’re seeing comes from an incompatibility between NumPy 2.x and some Whisper dependencies that were compiled against NumPy 1.x.

Solution: Downgrade NumPy

You can fix this by downgrading NumPy to version 1.x:

pip install "numpy<2"

Then run Whisper again:

whisper demo.mp4 --model medium --language auto --output_format txt

Hide warning UserWarning: FP16 is not supported on CPU; using FP32 instead

Option 1: Suppress all Python warnings (quick + global)

In your terminal or script, set the environment variable:

PYTHONWARNINGS="ignore" whisper dmeo.mp4 --model medium<br></code>

Or, in Python code:

import warnings

warnings.filterwarnings("ignore")

Option 2: Suppress only that specific warning

If you’re using faster-whisper in Python and want to filter only that one:

import warnings

warnings.filterwarnings(
    "ignore",
    message="FP16 is not supported on CPU; using FP32 instead"
)

Option 3: Patch the library (if you’re comfortable)

You can find the line in the faster_whisper source code (usually in transcribe.py) that issues the warning and comment it out or remove it:

# warnings.warn("FP16 is not supported on CPU; using FP32 instead")

Not recommended unless you maintain the code.