DevOps - DocRAG

abstract

Deployment architecture, services, environment variables, and operational runbooks for DocRAG — a self-hosted multimodal RAG engine.

Services Map

note

DocRAG exposes services on individual ports directly. There is no nginx or API gateway — the frontend calls the backend at http://localhost:8000 directly.


Docker Services

ServiceContainerImagePort(s)VolumePurpose
postgresdocrag-postgrespostgres:16-alpine5432./postgres_data:/var/lib/postgresql/dataChat session + message persistence
qdrantdocrag-vector-dbqdrant/qdrant:v1.17.06333 (HTTP), 6334 (gRPC)./qdrant_data:/qdrant/storage:zVector storage for document chunks
backenddocrag-apicustom build8000./backend:/app + named backend_venvFastAPI API server (hot-reload enabled)
frontenddocrag-uicustom build3000./frontend:/app + named frontend_node_modulesNext.js UI (hot-reload via npm run dev)

Startup order: qdrantpostgres (both health-checked) → backendfrontend

Health checks:

  • postgres: pg_isready -U postgres (10s interval, 5 retries)
  • qdrant: cat /proc/net/tcp | grep 18BD (hex port 6333; 10s interval, 3 retries)

Environment Variables

VariableRequiredSourceDescriptionDefault
POSTGRES_USERYespostgres imageDB superuser namepostgres
POSTGRES_PASSWORDYespostgres imageDB superuser passwordpassword
POSTGRES_DBYespostgres imageDatabase namedocrag_db
DB__USERYespydantic-settingsMust match POSTGRES_USERpostgres
DB__PASSWORDYespydantic-settingsMust match POSTGRES_PASSWORDpassword
DB__HOSTYespydantic-settingspostgres (service name in Docker)localhost
DB__PORTNopydantic-settingsPostgreSQL port5432
DB__NAMEYespydantic-settingsMust match POSTGRES_DBdocrag_db
QDRANT__HOSTNopydantic-settingsqdrant (service name in Docker)qdrant
QDRANT__PORTNopydantic-settingsQdrant HTTP API port6333
QDRANT__COLLECTION_NAMENopydantic-settingsVector collection namedoc_rag_knowledge
LLM__PROVIDERNopydantic-settingsActive LLM backendollama
LLM__OLLAMA_BASE_URLNopydantic-settingsOllama server URLhttp://localhost:11434
LLM__OPENAI_API_KEYNopydantic-settingsOpenAI API keynull
LLM__ANTHROPIC_API_KEYNopydantic-settingsAnthropic API keynull
LLM__GEMINI_API_KEYNopydantic-settingsGoogle Gemini API keynull
warning

PostgreSQL Docker image uses POSTGRES_* variables. pydantic-settings reads DB__* with __ as nested delimiter (→ Settings.DB). Both sets must be kept in sync in .env.

warning

Changing EMBED_MODEL (default: nomic-ai/nomic-embed-text-v1.5, 768 dims) after indexing data requires clearing the Qdrant collection. nomic vectors are 768-dim; the old default sentence-transformers/all-MiniLM-L6-v2 is 384-dim — mixing them will corrupt search.


Nginx Routing Rules

Not applicable — DocRAG does not use a reverse proxy. Ports are exposed directly.


Deployment Procedure

cp .env.example .env
# Edit .env with your passwords and API keys
docker-compose up --build
  • Frontend UI: http://localhost:3000
  • Backend API + Swagger: http://localhost:8000/docs
  • Qdrant Dashboard: http://localhost:6333/dashboard

With Local LLM (Ollama)

Set LLM__PROVIDER=ollama and LLM__OLLAMA_BASE_URL=http://host.docker.internal:11434 in .env. Ollama must be running on the host machine. The host.docker.internal DNS name resolves to the host from inside Docker containers.

Backend Only (Local Dev)

cd backend
uv sync
docker-compose up -d qdrant postgres   # still need the data stores
uv run uvicorn app.main:app --reload --port 8000

Frontend Only (Local Dev)

cd frontend
npm install
npm run dev

Backup & Restore

DataLocationNotes
Chat history (PostgreSQL)./postgres_data/Copy entire directory while container is stopped
Vector index (Qdrant)./qdrant_data/Copy entire directory while container is stopped
warning

DocRAG does not ship backup scripts. For production use, snapshot the postgres_data and qdrant_data bind-mount directories out-of-band.


Security Considerations

  • API keys (OpenAI, Anthropic, Gemini) are stored in AppSetting table (PostgreSQL) and returned masked via the settings API — see backend/app/api/v1/settings.py.
  • No authentication layer — DocRAG is designed for local/self-hosted use. Do not expose ports 3000 or 8000 to the public internet without adding auth.
  • CORS is configured in backend/app/main.py via CORSMiddleware.

Known Gotchas

  • DB__HOST must be postgres (service name) in Docker, but localhost for local dev. Failing to change this breaks the backend on startup.
  • backend_venv named volume caches the Python virtualenv; if you change pyproject.toml, run docker-compose down -v and rebuild to force a fresh uv sync.
  • Qdrant health check uses /proc/net/tcp hex port detection (18BD = 6333 in hex) — not a curl because curl is not in the image.
  • File size limit: file_service.validate_file() enforces 20 MB — hardcoded in backend/app/services/file_service.py.

RoleLink
Chat DB schemaDB - chatsession
Message DB schemaDB - chatmessage
Settings DB schemaDB - appsetting