Milvus: Install & Full Deployment
Standing up Milvus via Docker, then a full connect-to-query walkthrough — matching the deployment style of the MongoDB and MinIO docs.
This page covers standing up a Milvus server via Docker (for Milvus Lite, no server setup is needed — see 05- Milvus), then a full walkthrough from first connection through querying data back out.
Docker setup (Milvus standalone)
For a local Milvus server (not Lite), use a compose stack with etcd, MinIO, and Milvus standalone.
Example layout (tested on Apple Silicon; adjust platform for amd64 if needed):
Image tags below are current as of this doc’s writing — worth checking for newer releases before deploying.
# docker-compose.milvus.yml
services:
etcd:
image: quay.io/coreos/etcd:v3.5.5
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
- ETCD_QUOTA_BACKEND_BYTES=4294967296
- ETCD_SNAPSHOT_COUNT=50000
volumes:
- etcd_data:/etcd
command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
minio:
image: minio/minio:RELEASE.2023-03-20T20-16-18Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
volumes:
- minio_data:/minio_data
command: minio server /minio_data --console-address ":9001"
milvus:
image: milvusdb/milvus:v2.4.15
command: ["milvus", "run", "standalone"]
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
volumes:
- milvus_data:/var/lib/milvus
ports:
- "19530:19530"
- "9091:9091"
depends_on:
- etcd
- minio
attu:
image: zilliz/attu:v2.4.12
ports:
# GUI — open http://MILVUS_HOST:3001 in a browser
- "3001:3000"
environment:
# Attu runs inside Compose — use the Milvus *service name*, not MILVUS_HOST
MILVUS_URL: milvus:19530
MILVUS_USERNAME: root
MILVUS_PASSWORD: YOUR_PASSWORD
depends_on:
- milvus
volumes:
etcd_data:
minio_data:
milvus_data:
Start:
docker compose -f docker-compose.milvus.yml up -d
| Endpoint | URL |
|---|---|
| gRPC API | http://MILVUS_HOST:19530 |
| Attu (GUI) | http://MILVUS_HOST:3001 |
Authentication
The Milvus standalone image enables authentication by default. Credentials (replace YOUR_PASSWORD — default install uses Milvus):
| Field | Value |
|---|---|
| Username | root |
| Password | YOUR_PASSWORD |
| Token | root:YOUR_PASSWORD (username:password — pymilvus MilvusClient format) |
Attu uses the same credentials (MILVUS_USERNAME / MILVUS_PASSWORD in the compose file above). If you change the
Milvus password, update Attu and AnyLog to match.
Using Milvus Directly (outside AnyLog)
Everything above stands up a real, standalone Milvus instance — AnyLog is just one client talking to it over gRPC.
The same instance is fully usable on its own, which is useful for inspecting data AnyLog has written, running
ad-hoc searches without going through vector commands, or handing the same collection to a data science
workflow that has nothing to do with AnyLog.
Attu (the GUI)
Attu is Milvus’s own official admin console (by Zilliz), already running in the compose stack above at
http://MILVUS_HOST:3001. Once logged in (same root/YOUR_PASSWORD credentials as AnyLog), it lets you:
- Browse collections — schema, index type, row count, and load status, without writing a query
- Preview data — page through actual rows/vectors in a collection
- Run vector search interactively — paste in a query vector (or use Attu’s built-in embedding for text, if configured) and see nearest neighbors, without touching the CLI
- Manage indexes — create/drop/rebuild an index on a field, and switch metric type, outside of
vector create - View collection load state — Milvus collections must be “loaded” into memory before they’re searchable; Attu shows this state directly, which is useful for catching a collection that exists but isn’t actually queryable yet
This is often the fastest way to sanity-check that data AnyLog inserted actually looks right, before debugging further on the AnyLog side.
pymilvus (direct SDK access)
Since AnyLog is just a pymilvus client itself, you can connect to the exact same instance directly from Python,
independent of any AnyLog node:
from pymilvus import MilvusClient
client = MilvusClient(uri="http://MILVUS_HOST:19530", token="root:YOUR_PASSWORD")
# list collections AnyLog has created
print(client.list_collections())
# inspect a collection's schema directly
print(client.describe_collection("sensors"))
# query rows without going through AnyLog at all
results = client.query(collection_name="sensors", filter="subject == 'security'", output_fields=["id", "text", "subject"])
print(results)
This is the same client library milvus_dbms.py uses under the hood — nothing AnyLog-specific about the
connection itself, just a different consumer of the same data.
Metrics endpoint
Port 9091 (already exposed in the compose file above) is Milvus’s own Prometheus-compatible metrics endpoint —
independent of anything AnyLog reports via get processes/get streaming. Point a Prometheus/Grafana stack at
http://MILVUS_HOST:9091/metrics for Milvus-level operational metrics (query latency, memory usage, index build
time) if you’re monitoring Milvus as its own service rather than just through AnyLog’s lens.
Standalone vs. cluster mode, and backup
Everything in this doc deploys Milvus standalone (one node, backed by etcd + MinIO for metadata/object storage) — adequate for development and moderate production load. Milvus also supports a distributed cluster mode for horizontal scaling, which is a Milvus-level concern entirely separate from AnyLog’s own operator/cluster model. AnyLog does not replicate across multiple Milvus instances itself). If you outgrow standalone, that’s a Milvus deployment decision to make independent of AnyLog, following Zilliz’s own cluster deployment guidance.
For backup, since standalone Milvus stores its metadata in etcd and its actual vector/object data in MinIO (both
visible as their own services in the compose file above), backing up the etcd_data and minio_data volumes
covers the underlying state. Zilliz also publishes a dedicated
milvus-backup tool for logical collection-level backup/restore,
which is generally the more reliable option over raw volume snapshots.
Offline model setup
The text-embedding model (see 05- Milvus) needs internet access once to download. For an offline node, download it on a build machine and ship the cache over:
# build machine
export HF_HOME=/tmp/anylog-model-cache && mkdir -p "$HF_HOME"
python3 -c "from pymilvus import model; fn = model.DefaultEmbeddingFunction(); fn.encode_documents(['warmup']); fn.encode_queries(['warmup'])"
tar -C "$HF_HOME" -czf milvus-embedding-model.tgz hub
# target host (Docker default path)
mkdir -p /app/.anylog-model-cache
tar -xzf milvus-embedding-model.tgz -C /app/.anylog-model-cache
export HF_HOME=/app/.anylog-model-cache
export HF_HUB_OFFLINE=1 # optional
Full Deployment Walkthrough
Set MILVUS_HOST to the machine running the compose stack (localhost on the same machine, or the host IP from a
remote client) before starting.
- Bring up the Milvus stack (see Docker setup above)
docker compose -f docker-compose.milvus.yml up -d - Connect AnyLog to Milvus
connect dbms vectors where type = milvus and uri = http://MILVUS_HOST:19530 and token = root:YOUR_PASSWORD and dimension = 768Verify:
get databases - Create a collection
vector create where dbms = vectors and collection = sensors and metric_type = COSINEVerify:
vector list where dbms = vectors - Insert data
vector insert where dbms = vectors and collection = sensors and text = "door open" and subject = "security" vector insert where dbms = vectors and collection = sensors and text = "temperature high" and subject = "process" - Query data — semantic search
vector search where dbms = vectors and collection = sensors and query = "door open" and limit = 5See Query Data for what the result looks like and how to interpret the similarity score.
- Query across the network (if the collection is hosted on multiple operators)
run client () vector search where dbms = vectors and collection = sensors and query = "door open" and limit = 5 - Tear down
disconnect dbms vectorsdocker compose -f docker-compose.milvus.yml down
Quickstart (Milvus Lite, no Docker/server needed)
If you don’t need a full server deployment, the same flow works entirely locally against a Milvus Lite file:
connect dbms vectors where type = milvus and path = !data_dir/milvus_demo.db and dimension = 768
vector create where dbms = vectors and collection = sensors and metric_type = COSINE
vector insert where dbms = vectors and collection = sensors and text = "door open" and subject = "security"
vector insert where dbms = vectors and collection = sensors and text = "temperature high" and subject = "process"
vector search where dbms = vectors and collection = sensors and query = "door open" and limit = 5
vector query where dbms = vectors and collection = sensors and filter = "subject == 'security'"
get databases
Text embedding example (HISTORY_DOCS)
Three separate sentences (as in the Milvus quickstart) need three vector insert commands — one row per text value:
vector insert where dbms = vectors and collection = history and text = "Artificial intelligence was founded as an academic discipline in 1956." and subject = "history"
vector insert where dbms = vectors and collection = history and text = "Alan Turing was the first person to conduct substantial research in AI." and subject = "history"
vector insert where dbms = vectors and collection = history and text = "Born in Maida Vale, London, Turing was raised in southern England." and subject = "history"
vector search where dbms = vectors and collection = history and query = "Who worked on early artificial intelligence?" and limit = 3
If all sentences are in one text string (commas do not split documents):
vector insert where dbms = vectors and collection = history and text = "Artificial intelligence was founded as an academic discipline in 1956., Alan Turing was the first person to conduct substantial research in AI., Born in Maida Vale, London, Turing was raised in southern England." and subject = "history"
| Step | What happens |
|---|---|
| Processed by | pymilvus DefaultEmbeddingFunction (encode_documents) — ONNX model GPTCache/paraphrase-albert-onnx (~768 dimensions) |
| Inserted by | vector insert → milvus_dbms.py → Milvus insert — one entity, one vector for the full string |
Search embeds the query the same way (encode_queries) via vector search ... query = "...".
For bulk load from a file (many rows), use the standalone scripts under [path to milvus scripts]/milvusdb
(milvus_prepare_data.py → milvus_insert_data.py).
Troubleshooting
Milvus library not installed
pip install "pymilvus[milvus_lite,model]>=3.0.0" "transformers>=4.36,<5" onnxruntime
For Nuitka: reinstall deps, then rebuild ./build/nuitka_core.sh.
Collection exists without auto_id
Recreate:
vector create where dbms = vectors and collection = sensors and drop = true
Embedding model unavailable (offline)
Provide explicit vectors instead of text / query:
vector insert where dbms = vectors and collection = sensors and vector = [0.1,0.2,...] and text = "label only"
onnxruntime Unknown CPU vendor warning
Harmless on some CPUs / Docker (especially Apple Silicon). Embedding still works if the command completes.
Suppress gRPC stderr (optional)
export GRPC_VERBOSITY=NONE
export GLOG_minloglevel=3
Related
- 05- Milvus — concepts, connection reference, and the full
vectorcommand set