A high-performance vector database and search engine built in Rust, designed for semantic search.
5.0K
?? Docker Hub: https://hub.docker.com/r/hivehub/vectorizer
A high-performance vector database and search engine built in Rust, designed for semantic search, document indexing, and AI-powered applications. The v3.x line ships a binary RPC transport (MessagePack over TCP, port 15503) as the recommended primary channel alongside REST + MCP on 15002.
v3.6.1 highlights:
arm64 -fastembed image now starts. hivehub/vectorizer:3.5.0-fastembed and 3.4.0-fastembed exit 127 on linux/arm64 with error while loading shared libraries: libstdc++.so.6: the runtime stage copied an amd64 library into the arm64 image, and cross-linking succeeded because the linker reads a different path than the runtime does. The slim default image was never affected - it does not load that library. If you run the dense variant on arm64, 3.6.1 is the first working release.GET /collections could answer with a partial list whose total_collections agreed with it - a 181-collection store reporting "11 collections, total 11" seconds after boot. The response now carries loading, loaded_collections and expected_collections, and a new GET /ready answers 503 + Retry-After until the catalog is in. Gate your orchestrator on /ready; /health stays a liveness check and keeps answering 200 during warm-up on purpose.vectorizer:// URL up front instead of failing later inside reqwest, and points you at RpcClient::connect_url.Full 3.6.0 and 3.6.1 notes are in the changelog linked below.
Earlier in v3.x: 3.6.0 added collection TTL with read-back and full RPC parity; 3.5.0 fixed BM25 vocabulary loss across restarts, made the WAL fsync and checksum its records, removed a bulk_update_metadata deadlock, and unblocked search during batch inserts; 3.4.0 made /data the canonical volume mount.
Full changelog: CHANGELOG.md.
docker run -d \
--name vectorizer \
-p 15002:15002 \
-p 15503:15503 \
--restart unless-stopped \
hivehub/vectorizer:3.6.1
First boot creates an admin user and writes credentials to /data/.root_credentials inside the container (read with docker exec + cat or docker cp - the image is distroless so there's no shell). Rotate via the dashboard or /auth API as soon as you've copied them.
docker run -d \
--name vectorizer \
-p 15002:15002 \
-p 15503:15503 \
-v vec-data:/data \
--restart unless-stopped \
hivehub/vectorizer:3.6.1
The image defaults VECTORIZER_DATA_DIR=/data, so a single -v vec-data:/data mount captures the entire persistent state (.vecdb store, auth keys, JWT secret, snapshots, fastembed cache when enabled). docker compose up -d --force-recreate vectorizer is now safe - collections survive the recreate.
Upgrading from 3.3.0? 3.3.0 wrote state to
/.local/share/vectorizer/(the XDG path) on the container's writable layer despite the README advertising/data. If your existing setup mounted both/dataand/.local/share/vectorizeras a workaround, copy state from the workaround volume into/dataand drop the second mount. Full runbook:docs/users/configuration/DATA_DIRECTORY.md (issue #300).
services:
vectorizer:
image: hivehub/vectorizer:3.6.1
container_name: vectorizer
# Distroless nonroot (UID 65532) refuses host-UID bind mounts on
# Docker Desktop for Windows / macOS; flip to `user: root` if your
# host can't align UIDs. On Linux with a named volume or a
# UID-65532-owned bind mount, remove this.
# user: root
ports:
- "15503:15503" # VectorizerRPC (binary MessagePack over TCP - primary)
- "15002:15002" # REST + MCP + GraphQL + Dashboard
volumes:
# v3.4.0+ canonical mount - VECTORIZER_DATA_DIR defaults to /data.
- vec-data:/data
environment:
- VECTORIZER_HOST=0.0.0.0
- VECTORIZER_PORT=15002
- VECTORIZER_AUTH_ENABLED=true
- VECTORIZER_ADMIN_USERNAME=admin
- VECTORIZER_ADMIN_PASSWORD=change-me-in-production
- VECTORIZER_JWT_SECRET=change-this-to-a-random-32-char-secret
restart: unless-stopped
volumes:
vec-data:
? Healthcheck note. Since v3.0.1 the image ships a static
busyboxat/busyboxand a built-inHEALTHCHECK(/busybox wget -q --spider http://127.0.0.1:15002/health).docker compose psreports(healthy)once the server is up - no overrides needed. If you customize the healthcheck on Compose / Kubernetes, point it at the same/busybox wgetcommand or use a TCP probe;curlandshare still absent from the runtime image.
VECTORIZER_DATA_DIR=/data so a single -v vec-data:/data mount captures collections, auth keys, JWT secret, snapshots, and the fastembed cache. Linux startup emits WARN data dir at <path> is ephemeral; recommend mounting a volume when the resolved dir has no backing mount, so a forgotten --volume flag fails loud instead of silently wiping collections on --force-recreate. New --data-dir <path> CLI flag for non-/data deployments.embedding_provider / model contract - POST /collections and POST /embed reject unknown providers with 400 unsupported_provider { requested, available } / 400 unsupported_model { requested, available } instead of silently coercing to BM25. GET /stats lists every registered provider with dimension + default flag; mirrored as the list_providers MCP tool. CollectionConfig.embedding_provider persists which provider the collection was created with.429 Too Many Requests + Retry-After on overload, BM25 vocab-build semaphore, structured queue_full MCP error, gRPC RESOURCE_EXHAUSTED. Configured via backpressure.{max_concurrent_vocab_builds,upsert_queue_high_water,upsert_queue_hard_limit} in config.yml. All five first-party SDKs honor Retry-After (1 s default, 30 s cap, 3 retries).POST /insert_texts and POST /insert use the request id verbatim as Vector.id (or <id>#<chunkIndex> for chunked entries). Re-running the same payload upserts in place. Bulk POST /insert_vectors ingests pre-computed embeddings without going through the embedding pipeline.15503, ~10� lower per-frame overhead than REST/JSON. Default binary transport across every SDK (Rust, TypeScript, Go, Python, C#).all-MiniLM-L6-v2 (384-dim), all-MiniLM-L12-v2, all-mpnet-base-v2, bge-small-en-v1.5 (384), bge-base-en-v1.5 (768), bge-large-en-v1.5 (1024), plus -q int8-quantized variants (selected via embedding.model: fastembed:<id> in config.yml - use the bare id, not the Xenova/ HF path). The default hivehub/vectorizer:3.5.0 image is BM25-only (~91 MB); hivehub/vectorizer:3.5.0-fastembed is a published image with FastEmbed compiled in and all-MiniLM-L6-v2 pre-fetched - no self-build required..vecdb format with 20-30% space savings, MMap support for datasets larger than RAM, automatic snapshots./qdrant/collections/{name}/points/* surface for migrations.POST /mcp (streamable HTTP).auth.enabled: true./prometheus/metrics (now including upsert_queue_depth, upsert_in_flight, vocab_build_permits_available, upsert_rejected_total{reason}, bm25_empty_vocab_fallback_total{collection}), OpenTelemetry OTLP export, structured tracing via RUST_LOG. Operator runbook at docs/deployment/backpressure.md and importable Grafana panels at docs/grafana/backpressure-panels.json.| Tag | Points to | Notes |
|---|---|---|
3.6.1 | v3.6.1 release | Current stable. Startup-warm-up readiness (GET /ready, loading on /collections); SDK-validator-compatible search envelopes; collection TTL read-back. BM25-only (~91 MB). |
3.6.1-fastembed | v3.6.1 release | Same server with FastEmbed compiled in and all-MiniLM-L6-v2 (384-dim dense) pre-fetched. First release where this variant runs on linux/arm64 - 3.4.0 and 3.5.0 shipped an amd64 libstdc++ inside the arm64 image and exited 127 on start. |
3.6.0 | v3.6.0 release | Collection TTL, RPC parity, Thunder transport. ?? 3.6.0-fastembed is broken on arm64; the amd64 image is fine. |
3.5.0 | v3.5.0 release | BM25-restart + WAL-durability fixes; search unblocked during batch insert; MCP?REST parity; first-boot-with-defaults works; 0 CRITICAL/0 HIGH CVEs with an attached OpenVEX attestation. |
3.5.0-fastembed | v3.5.0 release | Same server with FastEmbed pre-fetched. ?? does not start on linux/arm64 (libstdc++.so.6 not found) - use 3.6.1-fastembed. |
3.4.0 | v3.4.0 release | /data canonical volume mount (#300); embedding_provider / model honoured contracts (#306). ?? ships 31 base-image CVEs (4 HIGH) fixed in 3.5.0 - upgrade. |
3.3.0 | v3.3.0 release | Hardened dashboard cookies + CSRF; API key usage metrics. ?? has the persistence trap fixed in 3.4.0. |
3.2.0 | v3.2.0 release | Bulk-upsert backpressure, Retry-After SDKs, new Prometheus metrics. |
3.1.0 | v3.1.0 release | /insert_vectors, stable client-id upserts, flat chunked-payload layout. |
3.0.2 | v3.0.2 release | Docker Hardened Image base (dhi.io/debian-base:trixie); ~88 MB compressed; Scout-compliant. |
latest | same as 3.6.1 | Updated on every stable tag, and always the slim default variant - never the -fastembed one. Pin to a specific version in production. |
Older 1.x / 2.x tags remain on Docker Hub for rollback but are no longer receiving updates.
| Endpoint | Purpose |
|---|---|
tcp://localhost:15503 | VectorizerRPC (binary MessagePack - primary transport) |
http://localhost:15002 | REST API |
http://localhost:15002/dashboard/overview | Web Dashboard (React + TS) |
http://localhost:15002/dashboard/setup | First-run setup wizard |
http://localhost:15002/dashboard/docs | Swagger/OpenAPI browser |
http://localhost:15002/graphql | GraphQL endpoint |
http://localhost:15002/mcp | MCP server (streamable HTTP, protocol 2025-03-26) |
http://localhost:15002/umicp | UMICP transport discovery |
http://localhost:15002/health | Health check (anonymous, returns {"status":"healthy","version":"3.5.0",...}) |
http://localhost:15002/prometheus/metrics | Prometheus scrape target |
| Variable | Default | Purpose |
|---|---|---|
VECTORIZER_HOST | 0.0.0.0 | Bind address. |
VECTORIZER_PORT | 15002 | REST + MCP + dashboard port. |
VECTORIZER_DATA_DIR | /data | v3.4.0+ - persistent state dir (collections, auth keys, JWT secret, snapshots, fastembed cache). Set to a non-/data path if your mount targets a different location; the resolver propagates to every persistence subsystem. |
VECTORIZER_AUTH_ENABLED | (unset) | Set to true to gate data routes behind JWT/API-key. The default image ships auth.enabled: true. |
VECTORIZER_ADMIN_USERNAME | admin | Admin username seeded on first boot. |
VECTORIZER_ADMIN_PASSWORD | (auto-generated) | Admin password. Set this in production; otherwise the server writes a generated one to /data/.root_credentials. |
VECTORIZER_JWT_SECRET | (auto-generated in 3.5.0) | v3.5.0: an empty secret is auto-generated and persisted to /data/jwt_secret.key on first boot (with a loud warning) instead of failing to start. Set an explicit ?32-char secret in production and share it across HA-cluster nodes so JWTs stay portable across restarts and nodes. |
CORTEX_VECTORIZER_BACKPRESSURE_ENABLED | true | v3.2.0+ - global enable for the bulk-upsert backpressure layer. |
CORTEX_VECTORIZER_MAX_CONCURRENT_BUILDS | num_cpus | v3.2.0+ - semaphore for the BM25 vocab-build hot path. |
CORTEX_VECTORIZER_UPSERT_HIGH_WATER | 256 | v3.2.0+ - per-collection in-flight-depth at which the server emits a structured warn + bumps upsert_rejected_total{reason="queue_high_water_warn"} (still admits the request). |
CORTEX_VECTORIZER_UPSERT_HARD_LIMIT | 1024 | v3.2.0+ - per-collection in-flight-depth at which new upserts are refused with 429 Too Many Requests + Retry-After. |
RUST_LOG | info | Per-module tracing filter, e.g. vectorizer=debug,hyper=info. |
TZ | Etc/UTC | Container timezone. |
RUN_MODE | production | production or development. |
config.yml to /vectorizer/config.yml to override defaults (embedding model, quantization, HNSW params, auth mode, replication topology). Set embedding.model: fastembed:all-MiniLM-L6-v2 (or any other fastembed id) to register a dense provider as the default - note that the default published image is BM25-only; build with --build-arg ENABLE_FASTEMBED=1 --build-arg NO_DEFAULT_FEATURES=0 --build-arg FEATURES=fastembed to get fastembed compiled in.workspace.yml to /vectorizer/workspace.yml + bind the source tree as /workspace:ro for monorepo indexing (the file-watcher service re-indexes on change).# First-boot admin password was written to /data/.root_credentials.
# Read it (distroless image - no shell, so cat the file via exec):
# docker exec vectorizer cat /data/.root_credentials
# Then login to get a JWT:
TOKEN=$(curl -sS -X POST http://localhost:15002/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"<password-from-.root_credentials>"}' \
| jq -r .access_token)
# Create a collection (dim 512 matches the default BM25 embedder)
curl -X POST http://localhost:15002/collections \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"docs","dimension":512,"metric":"cosine"}'
# Insert text with automatic embedding generation
curl -X POST http://localhost:15002/insert_texts \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"collection":"docs",
"texts":[
{"id":"doc_1","text":"Vectorizer is a high-performance vector database","metadata":{"tag":"intro"}},
{"id":"doc_2","text":"Rust is a systems programming language focused on safety","metadata":{"tag":"rust"}}
]
}'
# Semantic search by text
curl -X POST http://localhost:15002/collections/docs/search/text \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"query":"vector database","limit":10}'
# Direct vector search
curl -X POST http://localhost:15002/search \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"collection":"docs","vector":[0.1, 0.2, 0.3, ...], "limit":10}'
# Create a long-lived key
curl -X POST http://localhost:15002/auth/keys \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"my-service","permissions":["read","write","create_collection","delete_collection"]}'
# Use it via X-API-Key header
curl -H "X-API-Key: <api-key-from-response>" http://localhost:15002/collections
{
"mcpServers": {
"vectorizer": {
"type": "http",
"url": "http://localhost:15002/mcp",
"headers": { "X-API-Key": "<api-key>" }
}
}
}
curl -X POST http://localhost:15002/graph/discover/docs \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"similarity_threshold":0.7,"max_per_node":10}'
dhi.io/debian-base:trixie (Docker Hardened Image - Docker-signed, Scout-native, weekly rebuilds, CIS-compliant), pinned by digest in 3.5.0 for reproducible builds. v3.0.0 shipped on gcr.io/distroless/cc-debian12:nonroot; v3.0.2 swapped to DHI to make Scout's "Approved Base Images" + "Up-to-Date Base Images" policies flip to Compliant.tar file-smuggling, glibc regex DoS the binary never triggers, systemd code that never runs in the container) are declared not_affected in an OpenVEX attestation attached to the image, each with a written justification. A CI gate (docker-cve-gate.yml) re-scans weekly + on release and fails on any new fixable CRITICAL/HIGH.COPY in the runtime stage is --chown=65532:65532 so the binary writes config.yml / workspace.yml on first boot without --user root.linux/amd64, linux/arm64 (multi-arch manifest)bash + full libssl/libcrypto/libsystemd/libreadline).HEALTHCHECK ... CMD ["/busybox", "wget", "-q", "--spider", "http://127.0.0.1:15002/health"] (a static busybox:stable-musl is COPY-ed into /busybox and used only as the healthcheck entrypoint).--package vectorizer-server --bin vectorizer --no-default-features (excludes ONNX / FastEmbed / GPU / Transmutation from the default image to keep the dependency surface small). The container binary is compiled with the dedicated release-docker Cargo profile (lto = false, codegen-units = 16, inherits release otherwise) - same opt-level=3 + strip behavior as the host cargo build --release, but ~30% faster to compile inside BuildKit at the cost of ~10-15% lower throughput on hot paths versus a host-built release binary. Operators chasing peak per-op throughput should rebuild from source with the workspace release profile.mode=max provenance attached as in-toto attestations to the multi-arch manifest list (Docker Scout reads from there). Inspect with docker buildx imagetools inspect hivehub/vectorizer:<tag>. OpenContainer labels carry revision, source, and license metadata.docker run -d \
--name vectorizer \
-p 15002:15002 -p 15503:15503 \
-v vec-data:/data \
-v $(pwd)/workspace.yml:/vectorizer/workspace.yml \
-v $(pwd):/workspace:ro \
--restart unless-stopped \
hivehub/vectorizer:3.6.1
The -fastembed image is published - no self-build needed. It ships with FastEmbed compiled in and all-MiniLM-L6-v2 pre-fetched; a config file selects it as the default provider:
docker run -d \
--name vectorizer \
-p 15002:15002 -p 15503:15503 \
-v vec-data:/data \
-v $(pwd)/fastembed-config.yml:/vectorizer/config.yml:ro \
hivehub/vectorizer:3.6.1-fastembed
Where fastembed-config.yml carries (use the bare model id - Xenova/all-MiniLM-L6-v2 is rejected):
embedding:
model: fastembed:all-MiniLM-L6-v2
GET /stats.providers then lists both fastembed:all-MiniLM-L6-v2 (384-dim, default) and bm25 (512-dim, sparse fallback). Hybrid retrieval works out of the box. To compile fastembed into your own image instead, build with --build-arg ENABLE_FASTEMBED=1 --build-arg NO_DEFAULT_FEATURES=0 --build-arg FEATURES=fastembed.
docker run -d \
--name vectorizer \
-p 15002:15002 \
-e RUST_LOG="vectorizer=debug,vectorizer::replication=trace,hyper=info" \
-e RUST_BACKTRACE=1 \
hivehub/vectorizer:3.6.1
docker pull hivehub/vectorizer@sha256:f3a642d4662ff9bf0f1acdb74b6cd56f12e0e4ea5cdeb2128714087cea40cc47
Apache-2.0 License - see LICENSE.
?? Pull:
docker pull hivehub/vectorizer:3.6.1
docker pull hivehub/vectorizer:3.6.1-fastembed # dense embeddings pre-baked
docker pull hivehub/vectorizer:latest
# Or pin earlier v3.x stable points:
docker pull hivehub/vectorizer:3.6.0
docker pull hivehub/vectorizer:3.5.0
docker pull hivehub/vectorizer:3.4.0
docker pull hivehub/vectorizer:3.3.0
docker pull hivehub/vectorizer:3.2.0
?? Repository: https://hub.docker.com/r/hivehub/vectorizer
Content type
Image
Digest
sha256:401f87465…
Size
16.9 MB
Last updated
22 days ago
docker pull hivehub/vectorizer