Skip to content

pgvector (Postgres + vectors)

Curated name pgvector. A drop-in PostgreSQL 18 carrying the pgvector extension, in compose mode, with seeded dev credentials and a readiness healthcheck.

Everything a normal Postgres does, plus a vector column type and similarity search - for storing embeddings and doing nearest-neighbour queries (semantic search, RAG, recommendations). It is a full Postgres, so it loses nothing relative to the plain postgres service; reach for it when your app needs vectors. The extension is available but not enabled by default - turn it on once:

CREATE EXTENSION IF NOT EXISTS vector;

(in a migration, or by hand on first use).

At init, or to an existing workbench:

Terminal window
monoceros init acme --with-services=pgvector
monoceros add-service acme pgvector

You can even run it alongside a plain postgres (different service names, so no collision) if you want a relational DB and a vector store side by side. A second pgvector instance works the same way with --as:

Terminal window
monoceros add-service acme pgvector --as=embeddings
Terminal window
monoceros remove-service acme pgvector

Or delete the service’s block from acme.yml by hand and re-run monoceros apply acme - the yml is the source of truth. (Its data volume monoceros-acme-data-pgvector is removed with the workbench on monoceros remove, which backs it up first.)

acme.yml
services:
- name: pgvector # host name in the container + data dir name
image: pgvector/pgvector:pg18
port: 5432 # in-container port (feeds `monoceros tunnel`)
env:
POSTGRES_USER: ${POSTGRES_USER} # values live in acme.env
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- data:/var/lib/postgresql # the service's own Docker volume
restart: unless-stopped
healthcheck: # workspace waits for service_healthy
test: [CMD, pg_isready, -U, '${POSTGRES_USER}', -d, '${POSTGRES_DB}']
interval: 10s
timeout: 5s
retries: 5
connectionEnv: # → the workspace env vars below
URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${host}:${port}/${POSTGRES_DB}
HOST: ${host}
PORT: ${port}
USER: ${POSTGRES_USER}
PASSWORD: ${POSTGRES_PASSWORD}
DB: ${POSTGRES_DB}

The credentials are ${VAR} references; the real values live in acme.env (dev default monoceros for user, password, and database), so the yml stays shareable without baking credentials in (see Workbench configuration).

Monoceros injects a connection env into the workspace container, prefixed with the service name:

VariableValue (defaults)
PGVECTOR_URLpostgresql://monoceros:monoceros@pgvector:5432/monoceros
PGVECTOR_HOSTpgvector
PGVECTOR_PORT5432
PGVECTOR_USERmonoceros
PGVECTOR_PASSWORDmonoceros
PGVECTOR_DBmonoceros

The prefix is the service name, uppercased - so a plain postgres next to it stays POSTGRES_* while this one is PGVECTOR_*, no collision.