vLLM für Production-Deployment konfigurieren (komplexer)

Für einen Production-Einsatz möchte ich den Container im Hintergrund laufen lassen und sicherstellen, dass er nach einem Neustart automatisch startet. Außerdem mounte ich den Hugging Face Cache, damit Modelle nicht bei jedem Container-Start neu heruntergeladen werden müssen. Das spart euch die Zeit die sonst für den Download benötigt wird und führt zu einem meiner Meinung nach stabileren System. Einmal das sich das Modell als solches nicht ändern kann also ihr immer das exakt gleiche Verhalten habt und vor allem keine eventuellen Probleme mit dem Download Prozess selber und den vielen GB die so ein Modell groß ist.

Zuerst erstelle ich ein Verzeichnis auf meinem Server auf einem Laufwerk in dem die Modelle gespeichert werden sollen. Hier können schon schnell viele 100 GB zusammen kommen. Daher überlegt euch wie ihr die Modelle am besten verwaltet. Natürlich könnt ihr diesen Ordner mit den Modellen zusammen auch später auf ein anderes Laufwerk kopieren. Ich lege den Ordner jetzt einfach einmal im Homeverzeichnis ~/ meines Users an.

Befehl: mkdir -p ~/models

Jetzt stoppe ich den Test-Container (falls er noch läuft) mit Ctrl+C:

In einem nächsten Schritt starte ich den Container im Hintergrund mit einem Namen, einer Restart-Policy und dem gemounteten Modell-Cache neu.

Hinweis: Ich habe hier einige Versuche gebraucht bis ich überhaupt erfolgreich das Modell herunter laden konnte. Der Hintergrund für meine Problme war wohl einmal die Weichnachtszeit und das damit wohl große Datenaufkommen bei meinem Internetservice Anbieter vermutlich durch Streaming & Co. Bei dem jetzt folgenden docker run Befehl werden alle Modelle in eurem Home-Ordner im Unterordner models abgelegt mit jeweils dem Modellnamen den ihr im folgenden Befehl wenn ihr das Modell hinterlegt ändern müsst. Ich habe die anzupassenden 3 Stellen jeweils fett im Befehl hervorgehoben.

Model: Qwen2.5-Math-1.5B-Instruct

Befehl: docker run -it --rm --name vllm-Qwen2.5-Math-1.5B-Instruct -v ~/models:/data --dns 8.8.8.8 --dns 8.8.4.4 --ipc=host nvcr.io/nvidia/vllm:25.11-py3 /bin/bash -c "pip install hf_transfer && export HF_HUB_ENABLE_HF_TRANSFER=1 && python3 -c \"from huggingface_hub import snapshot_download; snapshot_download(repo_id='Qwen/Qwen2.5-Math-1.5B-Instruct', local_dir='/data/Qwen2.5-Math-1.5B-Instruct', max_workers=1, resume_download=True)\""

Hier noch ein weiteres Modell das ich erfolgreich herunter laden konnte.

Modell: openai/gpt-oss-20b

Befehl: docker run -it --rm --name vllm-gpt-oss-20b -v ~/models:/data --dns 8.8.8.8 --dns 8.8.4.4 --ipc=host nvcr.io/nvidia/vllm:25.11-py3 /bin/bash -c "pip install hf_transfer && export HF_HUB_ENABLE_HF_TRANSFER=1 && python3 -c \"from huggingface_hub import snapshot_download; snapshot_download(repo_id='openai/gpt-oss-20b', local_dir='/data/gpt-oss-20b', max_workers=1, resume_download=True)\""

Nachdem das Modell erfolgreich heruntergeladen wurde, starte ich jetzt den vLLM Server mit dem lokal gespeicherten Modell. Wichtig: Ich verwende den lokalen Pfad /data/gpt-oss-20b statt des Hugging Face Namens:

Befehl: docker run -d --gpus all --name vllm-server -p 8000:8000 --restart unless-stopped -v ~/models:/data --ipc=host --ulimit memlock=-1 --ulimit stack=67108864 nvcr.io/nvidia/vllm:25.11-py3 vllm serve /data/gpt-oss-20b --gpu-memory-utilization 0.6

Der Parameter -d startet den Container im Hintergrund, --name vllm-server gibt ihm einen Namen, --restart unless-stopped sorgt dafür, dass der Container nach einem Neustart automatisch wieder startet, und -v ~/models:/data mountet das lokale Modell-Verzeichnis. Mit /data/gpt-oss-20b verweise ich auf das lokal gespeicherte Modell.

Jetzt könnt ihr von jedem Computer im Netzwerk auf den vLLM Server zugreifen. Öffnet in eurem Browser oder mit cURL http://<IP-Adresse-AI-TOP-ATOM>:8000 (ersetzt dabei <IP-Adresse-AI-TOP-ATOM> mit der IP-Adresse eures AI TOP ATOM).

Dieser Befehl ist darauf optimiert, riesige Modell-Dateien stabil und performant von Hugging Face herunterzuladen, wobei typische Fehlerquellen (wie DNS-Probleme oder langsame Downloads) umgangen werden. Als ich diese Anleitung geschrieben habe über die Weihnachtsfeiertage 2025 hatte mein Internet-Provider wohl massive Bandbreitenprobleme und ich musste sehr häufig den Download von neuen starten da die DNS Auflösung des Providers nicht einmal mehr geklappt hatte.

Verwendete Docker Parameter

In dem von mir verwendeten docker run Befehl habe ich eine Vielzahl an Flags verwendet die ich euch nachfolgend einmal erklären möchte. Ob das für euch so wirklich sinnvoll ist kann ich nicht sagen aber als ich diesen Bericht geschrieben habe hatte ich Probleme mit der Internetversorgung und musste einen stabilen Aufruf schaffen mit dem ich die ca. 65 GB des gpt-oss-120b Modells herunter laden konnte. Zum testen damit es schneller geht habe ich gpt-oss-20b verwendet.

1. Die Laufzeit Parameter

Die jetzt folgenden Parameter beziehen sich alle darauf wie sich der erzeugte Docker Container zur Laufzeit verhält.

  • docker run: Der Basis-Befehl zum Erstellen und Starten eines neuen Containers.

  • -it: Kombiniert -i (interactive) und -t (tty). Dies ermöglicht es dir, die Fortschrittsbalken des Downloads live im Terminal zu sehen und bei Bedarf mit Strg+C zu interagieren.

  • --rm: „Auto-Remove“. Sorgt dafür, dass der Container nach Abschluss des Downloads sofort gelöscht wird. Das hält dein System sauber, da wir nur die Daten (im Volume) behalten wollen also der herunter geladene Modell, aber nicht den Container selbst.

  • --name vllm-gpt-oss-20b: Verweist auf einen festen Namen für den Container. Ohne diesen Parameter würde Docker einen zufälligen Namen vergeben. Mit Namen kannst du den Status in einem anderen Terminal via docker stats vllm-gpt-oss-20b leicht überwachen.

2. System- & Netzwerk-Konfiguration

Hier wird es etwas technisch und ich habe ein paar Stunden benötigt mit vielen Versuchen bis ich endlich ein Modell erfolgreich herunter laden konnte. Diese Parameter lösen daher spezifische Probleme bei großen Datenmengen.

  • -v ~/models:/data: Das Volume Mapping. Es verknüpft den Ordner ~/models auf deinem Rechner wie den AI TOP ATOM mit dem Pfad /data innerhalb des Containers. So landen die Gigabytes an Modelldaten direkt auf deiner Festplatte und nicht im flüchtigen Speicher des Containers. Das hat den großen Vorteil das Du so nicht immer wieder die Modelle herunter laden kannst sondern via vLLM schnell zwischen den Modellen wechseln kannst. Denn im Unterschied zu Ollama muss Du bei vLLM immer den Container mit einem spezifischen Modell neu starten.

  • --dns 8.8.8.8 --dns 8.8.4.4: Zwingt den Container, die Google-DNS-Server zu nutzen. Dies ist ein „Lifehack“ gegen den Fehler Temporary failure in name resolution, der oft auftritt, wenn der Standard-DNS bei tausenden Anfragen (wie beim Token-Refresh von Hugging Face) überlastet ist.

  • --ipc=host: Erlaubt dem Container den Zugriff auf den Shared Memory des Host-Systems. vLLM benötigt dies für die effiziente Datenverarbeitung zwischen verschiedenen Prozessen.

3. Das Container-Image

Hier sagen wir exakt welches Image verwendet werden soll aus den NVIDIA Playbooks für die DGX Spark und somit auch für meinen Gigabyte AI TOP ATOM ist es genau dieses Image das benötigt wird.

  • nvcr.io/nvidia/vllm:25.11-py3: Das offizielle vLLM-Image aus der NVIDIA Container Registry (NVCR). Die Version 25.11 zeigt an, dass es sich um ein Release (Stand Ende 2024/Anfang 2025) handelt, das bereits für modernste GPUs optimiert ist. Ich denke einmal es ist nicht das neueste aber wohl soweit stabil das die Macher des Playbooks sich für dieses entschieden haben.

4. Die Ausführungs-Logik (Bash-Scripting)

Alles hinter dem Image-Namen wird innerhalb des Containers ausgeführt. Ich habe diesen Weg so beschritten um für mich den Download-Prozess besser steuern zu können. Das waren für meine damaligen Download-Probleme die wichtigsten Parameter neben dem --dns Parameter.

  • /bin/bash -c "...": Startet eine Bash-Shell im Container, um eine Kette von Befehlen auszuführen.

  • pip install hf_transfer: Installiert ein spezialisiertes Rust-basiertes Paket, das Downloads von Hugging Face massiv beschleunigt, indem es Dateien in parallelen Streams lädt den ich aber wieder auf genau einen Prozess beschränkt habe mit dem max_workers=1 Parameter.

  • export HF_HUB_ENABLE_HF_TRANSFER=1: Aktiviert diesen High-Speed-Modus für die Hugging Face Library.

5. Das Python-Download-Skript

Jetzt kommen die Parameter die die Art und Weise des Downloads etwas beeinflussen.

  • snapshot_download(...): Die wohl sicherste Methode, um ein komplettes Modell-Repository herunterzuladen nach meinem Verständnis.

  • repo_id='openai/gpt-oss-20b': Die eindeutige Kennung des Modells auf Hugging Face.

  • local_dir='/data/gpt-oss-20b': Speicherziel innerhalb des Containers (das dank des Volume-Mappings auf deinem Rechner landet). Dieser Name wird später wieder wichtig wenn wir einen Container genau mit diesem oder einem anderen bereits herunter geladenen Modell starten wollen.

  • max_workers=1: Limitiert die Anzahl der parallelen Datei-Downloads. Bei instabilen Verbindungen oder DNS-Problemen ist „1“ oft die stabilste Wahl. Führte zwar immer noch zu Fehlermeldungen während dem Download aber war am Ende erfolgreich.

  • resume_download=True: Ein entscheidender Parameter! Er erlaubt es dem Skript, bei einem Abbruch genau dort weiterzumachen, wo es aufgehört hat, anstatt Gigabytes an Daten erneut zu laden. Allerdings war dieser Parameter wohl nicht länger unterstützt und kann wohl auch weg gelassen werden.

Das war es jetzt soweit mit den Parametern die ich verwendet habe.

Firewall Einstellungen (optional)

Falls eine Firewall aktiv ist, müsst ihr Port 8000 freigeben:

Befehl: sudo ufw allow 8000

Ihr könnt die Logs des Containers jederzeit einsehen:

Befehl: docker logs -f vllm-server

Hier geht es zum 3. Teil der Installations- und Konfigurationsanleitung.

vLLM auf Gigabyte AI TOP ATOM installieren: Hochperformante LLM-Inference mit OpenAI-kompatibler API – Teil 3-3