Milvus mit Docker installieren: Hochskalierbare Open-Source-Vektordatenbank für RAG und Semantic Search
Milvus (44k+ Stars) ist die meistgenutzte Open-Source-Vektordatenbank – das Fundament für RAG-Pipelines und Semantic Search. Diese Anleitung zeigt die Standalone-Installation per Docker Compose: .env, compose.yaml, Verifikation nach jedem Schritt.

Wer semantische Suche, RAG-Pipelines (Retrieval-Augmented Generation) oder Empfehlungssysteme im Produktivbetrieb aufbauen will, kommt an einer performanten Vektordatenbank nicht vorbei. Milvus ist mit über 44.000 GitHub-Stars die meistgenutzte Open-Source-Lösung in diesem Bereich – Apache-2.0-lizenziert, CNCF Incubating Project und speziell für die effiziente Ähnlichkeitssuche in Milliarden hochdimensionaler Vektoren (Embeddings) entwickelt. Diese Anleitung zeigt dir, wie du Milvus Standalone per Docker Compose plattformneutral auf einem Linux-Host, einer VM oder einem leistungsfähigen NAS aufsetzt, korrekt konfigurierst und betreibst.
Voraussetzungen
- Docker Engine 20.10+ und Docker Compose V2 (Plugin, Befehl
docker compose) installiert – nicht das veraltetedocker-compose(V1). Noch nicht installiert? Siehe Docker und Docker Compose auf Linux installieren. - x86_64-CPU mit SIMD-Extensions: SSE4.2, AVX oder AVX2 sind zwingend erforderlich. ARM64/Apple-Silicon ist für die Standalone-Docker-Variante nicht offiziell unterstützt.
- Mindestens 8 GB RAM (16 GB empfohlen); unter Last crashen etcd oder Milvus mit OOM-Kills, wenn zu wenig Arbeitsspeicher verfügbar ist.
- SSD-Storage mit mindestens 500 IOPS und unter 10 ms fsync-Latenz – etcd ist latenzempfindlich; auf HDDs oder langsamen NFS-Shares bricht der Dienst ab.
- Mindestens 20 GB freier Speicherplatz: Das Milvus-Image allein ist ca. 1,3 GB groß, dazu kommen etcd- und MinIO-Images sowie die Daten-Volumes.
- Stabile Internetverbindung für den initialen Image-Pull.
- Optional:
curlfür Health-Check-Verifikation undpython3 + pipfür einen pymilvus-Verbindungstest.
Schritt 1: Projektordner und Verzeichnisstruktur anlegen
Lege einen dedizierten Ordner für das Milvus-Projekt an. Alle Konfigurationsdateien und persistenten Daten werden hier gehalten. Ein sauberer, eigenständiger Ordner macht spätere Updates und Backups deutlich einfacher.
mkdir -p /opt/milvus
cd /opt/milvusMilvus legt seine Daten später automatisch unter ./volumes/ ab (gesteuert über die Variable DOCKER_VOLUME_DIRECTORY). Die drei Unterordner werden beim ersten Start durch Docker angelegt. Du kannst sie auch vorab manuell erstellen, um Berechtigungsproblemen unter Linux vorzubeugen:
mkdir -p /opt/milvus/volumes/etcd
mkdir -p /opt/milvus/volumes/minio
mkdir -p /opt/milvus/volumes/milvusVerifizieren: Prüfe, ob die Ordnerstruktur korrekt angelegt wurde:
ls -la /opt/milvus/volumes/
# Erwartete Ausgabe:
# drwxr-xr-x etcd/
# drwxr-xr-x minio/
# drwxr-xr-x milvus/Schritt 2: .env-Datei mit Secrets anlegen
Die .env-Datei enthält alle Zugangsdaten und anpassbaren Pfade. Die Standard-Credentials minioadmin/minioadmin sind nur für lokale Tests geeignet – für jeden produktionsnahen Betrieb musst du eigene, starke Passwörter setzen. Trage außerdem den absoluten Pfad als DOCKER_VOLUME_DIRECTORY ein, damit die Volumes immer am richtigen Ort landen, unabhängig davon, aus welchem Verzeichnis du docker compose aufrufst.
# /opt/milvus/.env
# Datenpfad fuer alle drei Volumes (absoluter Pfad empfohlen)
DOCKER_VOLUME_DIRECTORY=/opt/milvus
# MinIO Credentials - in Produktion UNBEDINGT aendern!
MINIO_ACCESS_KEY=meinSicheresMinioPasswort123
MINIO_SECRET_KEY=meinSicheresMinioSecret456Verifizieren: Prüfe, dass die Datei korrekt erstellt wurde und keine Syntaxfehler enthält:
cat /opt/milvus/.env
# Ausgabe: alle Zeilen sauber lesbar, keine BOM-Zeichen,
# kein Leerzeichen vor dem GleichheitszeichenSchritt 3: compose.yaml anlegen
Das folgende compose.yaml entspricht dem offiziellen Milvus-Standalone-Stack mit dem aktuellen Image-Tag v3.0-beta. Wer Produktionsstabilität auf der bewährten v2.5.x-Linie bevorzugt, ersetzt den Image-Tag durch milvusdb/milvus:v2.5.12 – die restliche Konfiguration bleibt identisch. Alle drei Dienste (etcd, minio, standalone) sind zwingend erforderlich; keiner kann weggelassen werden.
# /opt/milvus/compose.yaml
version: '3.5'
services:
etcd:
container_name: milvus-etcd
image: quay.io/coreos/etcd:v3.5.25
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
- ETCD_QUOTA_BACKEND_BYTES=4294967296
- ETCD_SNAPSHOT_COUNT=50000
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
command: >
etcd
-advertise-client-urls=http://etcd:2379
-listen-client-urls http://0.0.0.0:2379
--data-dir /etcd
healthcheck:
test: ["CMD", "etcdctl", "endpoint", "health"]
interval: 30s
timeout: 20s
retries: 3
restart: unless-stopped
minio:
container_name: milvus-minio
image: minio/minio:RELEASE.2024-05-28T17-19-04Z
environment:
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
ports:
- "9000:9000"
- "9001:9001"
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
command: minio server /minio_data --console-address ":9001"
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 30s
timeout: 20s
retries: 3
restart: unless-stopped
standalone:
container_name: milvus-standalone
image: milvusdb/milvus:v3.0-beta
command: ["milvus", "run", "standalone"]
security_opt:
- seccomp:unconfined
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
MINIO_REGION: us-east-1
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
ports:
- "19530:19530"
- "9091:9091"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
interval: 30s
start_period: 90s
timeout: 20s
retries: 3
depends_on:
etcd:
condition: service_healthy
minio:
condition: service_healthy
restart: unless-stopped
networks:
default:
name: milvusWichtige Details zur Konfiguration: Der etcd-Dienst advertised sich unter dem Docker-Service-Namen etcd (nicht localhost oder 127.0.0.1) – das ist zwingend, damit der Milvus-Container den etcd-Service korrekt erreicht. Der standalone-Container hat einen start_period von 90 Sekunden, weil der Startvorgang bei größeren Datenmengen länger dauern kann. Die Option seccomp:unconfined ist für manche internen Syscalls von Milvus erforderlich.
Verifizieren: Prüfe die compose.yaml auf YAML-Syntaxfehler, bevor du startest:
cd /opt/milvus
docker compose config
# Keine Fehlermeldung = Syntax korrekt;
# die geparste Konfiguration wird ausgegebenSchritt 4: Stack starten
Starte alle drei Container im Hintergrund. Docker Compose lädt zunächst die Images herunter (beim ersten Start ca. 1,5–2 GB Gesamtdownload), legt das Netzwerk milvus an und startet die Dienste in der durch depends_on und healthcheck definierten Reihenfolge: etcd und MinIO müssen healthy sein, bevor der Milvus-Container startet.
cd /opt/milvus
docker compose up -dDer gesamte Startvorgang dauert – je nach Hardware und Netzgeschwindigkeit – beim ersten Mal 3–8 Minuten. Beobachte den Fortschritt in Echtzeit:
docker compose logs -fWarte, bis du in den Logs keine Fehlermeldungen mehr siehst und der Milvus-Container meldet, dass der Proxy erfolgreich gestartet wurde.
Verifizieren: Alle drei Container müssen den Status Up (healthy) zeigen:
docker compose ps
# Erwartete Ausgabe (gekuerzt):
# NAME IMAGE STATUS
# milvus-etcd quay.io/coreos/etcd:... Up (healthy)
# milvus-minio minio/minio:... Up (healthy)
# milvus-standalone milvusdb/milvus:... Up (healthy)
# Zusaetzlicher Health-Check per curl:
curl http://localhost:9091/healthz
# Erwartete Ausgabe: OKSchritt 5: WebUI und MinIO-Konsole aufrufen
Milvus bringt ab v2.5 eine eingebaute WebUI mit, über die du Collections einsehen, Datenbankstatistiken abrufen und einfache Abfragen ausführen kannst. Die MinIO-Konsole ermöglicht einen Blick auf die intern gespeicherten Segment- und Indexdateien.
| Dienst | URL | Zugangsdaten |
|---|---|---|
| Milvus WebUI | http://localhost:9091/webui/ | keine (Auth deaktiviert) |
| Milvus Health | http://localhost:9091/healthz | – |
| MinIO Konsole | http://localhost:9001 | aus .env (Standard: minioadmin) |
| Milvus API | http://localhost:19530 | keine (Auth deaktiviert) |
Verifizieren: Rufe die WebUI im Browser auf und prüfe, ob die Startseite lädt:
curl -I http://localhost:9091/webui/
# Erwartete Ausgabe: HTTP/1.1 200 OK
curl -I http://localhost:9001
# Erwartete Ausgabe: HTTP/1.1 200 OK (MinIO-Konsole)Schritt 6: Verbindungstest mit pymilvus
Der schnellste Praxistest ist eine Python-Verbindung über das offizielle SDK pymilvus. Installiere es in einer virtuellen Umgebung oder direkt per pip:
pip install pymilvusFühre dann folgenden Schnelltest aus – er verbindet sich auf Port 19530, listet vorhandene Datenbanken auf und gibt die Serverversion aus:
python3 - <<'EOF'
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
print("Verbunden! Serverversion:", client.get_server_version())
print("Datenbanken:", client.list_databases())
client.close()
EOFVerifizieren: Die Ausgabe sollte in etwa so aussehen:
# Erwartete Ausgabe:
# Verbunden! Serverversion: v3.0.0-beta ...
# Datenbanken: ['default']Erscheint stattdessen ein Verbindungsfehler, prüfe zuerst docker compose ps (alle drei Container healthy?) und dann docker compose logs standalone auf Fehlermeldungen.
Eckdaten im Überblick
| Parameter | Wert | Hinweis |
|---|---|---|
| Image (aktuell) | milvusdb/milvus:v3.0-beta | Alternativ: v2.5.12 (LTS) |
| Begleit-Images | quay.io/coreos/etcd:v3.5.25 | Exakte Tags verwenden |
| MinIO-Image | minio/minio:RELEASE.2024-05-28T17-19-04Z | Exakten Tag beibehalten |
| API-Port | 19530 | gRPC + REST, SDK-Endpunkt |
| WebUI / Health | 9091 | /webui/ und /healthz |
| MinIO API | 9000 | intern genutzt |
| MinIO Konsole | 9001 | Browser-Verwaltung |
| etcd Ports | 2379/2380 | kein Host-Port-Mapping |
| Min. RAM | 8 GB (16 GB empfohlen) | Pflicht für stabilen Betrieb |
| CPU | x86_64 + SSE4.2/AVX | ARM64 nicht offiziell |
| Storage | SSD, >500 IOPS, <10ms fsync | HDD für etcd ungeeignet |
Troubleshooting / Typische Fehler
- „Illegal instruction" / Container crasht sofort beim Start: Milvus prüft beim Hochfahren auf AVX/SSE4.2. Auf älteren CPUs oder VMs ohne CPU-Feature-Passthrough schlägt das fehl. Lösung: CPU-Flags in der VM-Konfiguration aktivieren (z. B. in Proxmox CPU-Typ auf
hostoderx86-64-v3stellen) oder neuere Hardware nutzen. - „rpc error: code = Internal desc = stream terminated by RST_STREAM": etcd ist falsch advertised. Die
-advertise-client-urlsim Command muss den Docker-Service-Namenetcdverwenden, nichtlocalhostoder127.0.0.1. Prüfe, ob dascompose.yamlunverändert ist. - MinIO-Authentifizierungsfehler (403 beim Start): Tritt auf, wenn MinIO-Image-Tag und Credential-Variablennamen nicht zueinander passen. Neuere MinIO-Images erwarten
MINIO_ROOT_USER/MINIO_ROOT_PASSWORD; das hier verwendete TagRELEASE.2024-05-28nutzt nochMINIO_ACCESS_KEY/MINIO_SECRET_KEY. Den exakt referenzierten Tag immer beibehalten. - depends_on / Startreihenfolge funktioniert nicht: Das passiert mit Docker Compose V1 (
docker-compose, Python). Nur Docker Compose V2 (Go-Plugin,docker compose) unterstütztcondition: service_healthykorrekt. Version prüfen mit:docker compose version. - Volume-Berechtigungsfehler unter Linux: Wenn die
volumes/-Unterordner alsrootangelegt wurden, hat der Container-interne User keinen Schreibzugriff. Lösung: Ordner vorab mitchmod 777oder dem korrekten Container-UID anlegen. - Port 9091 bereits belegt: Prometheus oder andere Monitoring-Tools nutzen oft ebenfalls Port 9091. Lösung: Port-Mapping in der
compose.yamlanpassen, z. B."19091:9091". - OOM-Kill nach kurzer Zeit: Symptom: Container startet, stirbt nach wenigen Minuten. Ursache: zu wenig RAM. Unter Docker Desktop (macOS/Windows) das Memory-Limit in den Einstellungen auf mindestens 10 GB erhöhen.
- etcd bricht mit „took too long to execute" ab: Der Storage ist zu langsam. etcd benötigt unter 10 ms fsync-Latenz – auf HDD oder langsamen NFS-Shares funktioniert das nicht zuverlässig.
- seccomp:unconfined nicht erlaubt: Auf manchen Managed-Plattformen oder gehärteten Systemen ist diese Option verboten. In dem Fall muss ein spezifisches seccomp-Profil für Milvus erstellt werden oder ein anderer Host genutzt werden.
- Datenverlust nach docker compose down -v:
docker compose downallein entfernt nur Container, nicht die Volumes. Mit dem Flag-voder manuellemrm -rf volumes/gehen alle Daten unwiederbringlich verloren – vor jedem Update dievolumes/-Verzeichnisse sichern.
Häufige Fragen
Wie verbinde ich mich per Python nach dem Start?
Mit pymilvus über Port 19530 – ohne aktivierte Authentifizierung ist kein Token notwendig:
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")Das ist der Standard-Einstiegspunkt für alle SDK-basierten Operationen: Collections anlegen, Daten einfügen, Vektoren suchen.
Wie aktiviere ich die Authentifizierung?
Lade die offizielle milvus.yaml herunter, setze den Eintrag common.security.authorizationEnabled: true und binde die Datei als Volume in den standalone-Dienst ein:
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
- ./milvus.yaml:/milvus/configs/milvus.yamlNach einem Neustart des Containers (docker restart milvus-standalone) ist Authentifizierung aktiv. Standard-Admin-Zugangsdaten: root / Milvus – sofort ändern!
Was ist der Unterschied zwischen Milvus Standalone und Cluster?
Standalone läuft als einzelner Prozess (alle Komponenten in einem Container) und eignet sich für Entwicklung und kleinere Produktionsszenarien bis etwa 100 Millionen Vektoren. Der Cluster-Modus verteilt QueryNode, DataNode und IndexNode auf mehrere Container oder Hosts für horizontale Skalierung in den Milliardenbereich. Für die meisten KMU-Anwendungsfälle – RAG mit einer mittelgroßen Dokumentenbasis, Produktempfehlungen, interne Semantic Search – ist Standalone mehr als ausreichend.
Wie prüfe ich, ob Milvus erfolgreich gestartet ist?
Drei zuverlässige Methoden: (1) docker compose ps – alle drei Container müssen Up (healthy) zeigen. (2) curl http://localhost:9091/healthz muss OK zurückgeben. (3) WebUI im Browser aufrufen: http://localhost:9091/webui/ – lädt die Oberfläche, ist Milvus betriebsbereit.
Wie aktualisiere ich Milvus auf eine neue Version?
Erst ein Backup der volumes/-Verzeichnisse anlegen, dann Image-Tag in der compose.yaml anpassen und anschließend:
cd /opt/milvus
docker compose pull
docker compose up -dBei einem Major-Versionswechsel (z. B. 2.x auf 3.x) unbedingt die offiziellen Migrationshinweise in der Milvus-Dokumentation lesen, da Schema- und Datenformat-Änderungen möglich sind.
Gibt es eine grafische Verwaltungsoberfläche?
Ja, zwei Optionen: (1) Die eingebaute WebUI unter http://localhost:9091/webui/ ist ab v2.5 ohne zusätzliche Installation verfügbar. (2) Attu ist ein separates Open-Source-GUI (docker pull zilliz/attu), das sich über Port 19530 mit Milvus verbindet und erweiterte Funktionen wie Collection-Management, Datenvisualisierung und interaktive Vektorsuche bietet.
Kann ich Milvus für produktive RAG-Systeme einsetzen?
Ja – Milvus ist explizit für den Produktiveinsatz entwickelt und bildet das Datenfundament vieler produktiver RAG-Pipelines. Für den Aufbau eines vollständigen lokalen RAG-Systems empfiehlt sich außerdem ein Blick auf Lokales RAG-System mit Qdrant und Embeddings für einen direkten Vergleich der Ansätze, sowie auf RAG produktiv betreiben: Chunking, Hybrid-Search und Reranking für fortgeschrittene Pipeline-Optimierung.
Fazit
Milvus ist die erste Wahl, wenn du eine hochskalierbare, produktionsreife Vektordatenbank auf eigener Infrastruktur betreiben willst. Der Standalone-Stack per Docker Compose ist in etwa 20 Minuten einsatzbereit – vorausgesetzt, die Hardware-Anforderungen (x86_64-CPU mit AVX, SSD, 8 GB RAM) sind erfüllt. Die drei zwingend benötigten Container (Milvus, etcd, MinIO) arbeiten über ein internes Docker-Netzwerk zusammen; nach außen sind nur die wirklich benötigten Ports exponiert.
Für den Produktiveinsatz solltest du zusätzlich die Authentifizierung aktivieren, die Standard-MinIO-Credentials in der .env durch starke Passwörter ersetzen und einen regelmäßigen Backup-Job auf die volumes/-Verzeichnisse einrichten. Einen stabilen Einstieg in sichere Docker-Compose-Konfigurationen bietet Docker Compose absichern: Secrets, Healthchecks und Non-Root.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
- Lokales RAG-System mit Qdrant und Embeddings selbst bauen
- RAG produktiv betreiben: Chunking, Hybrid-Search, Reranking und Antwortqualität messen
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only
- Ollama und Open WebUI mit Docker: eigenes lokales KI-Sprachmodell
Offizielle Quellen: Milvus-Dokumentation: Docker Compose Installation (Standalone) | Offizielles Standalone Compose-File auf GitHub | milvusdb/milvus auf Docker Hub