Docker Setup
This guide covers running Pensieve using Docker containers. You can either build images from source or use the pre-built images published to the GitHub Container Registry (GHCR).
For a single-command setup using Docker Compose, see the Docker Compose guide.
Prerequisites
| Tool | Version | Purpose |
|---|---|---|
| Docker | ≥ 20.10 | Container runtime |
Option A: Pre-built Images (Recommended)
The easiest way to get started. Pre-built images are published to GHCR for every release:
| Image | Description |
|---|---|
ghcr.io/5000k/pensieve-backend:latest |
FastAPI backend |
ghcr.io/5000k/pensieve-frontend:latest |
Nginx-served React frontend |
Pull the Images
docker pull ghcr.io/5000k/pensieve-backend:latest
docker pull ghcr.io/5000k/pensieve-frontend:latest
Run the Backend
docker run -d \
--name pensieve-backend \
-p 8000:8000 \
-e OPENAI_API_KEY=sk-your-openai-api-key \
-e SEARCH_API_KEY=tvly-your-tavily-api-key \
-v $(pwd)/config.yaml:/app/config.yaml:ro \
-v $(pwd)/workspaces:/app/workspaces \
ghcr.io/5000k/pensieve-backend:latest
Run the Frontend
docker run -d \
--name pensieve-frontend \
-p 3000:80 \
ghcr.io/5000k/pensieve-frontend:latest
The frontend is now available at http://localhost:3000 and the backend API at http://localhost:8000.
Note: The pre-built frontend image connects to the backend at
http://localhost:8000by default. To use a different backend address, passVITE_API_URLandVITE_WS_URLat runtime — see Customizing the Frontend API URL below.
Option B: Build from Source
If you want to customize the images or run the latest code from the repository:
Clone the Repository
git clone https://github.com/5000K/pensieve.git
cd pensieve
Build the Backend Image
docker build -t pensieve-backend .
This uses the Dockerfile in the repository root. The image:
- Starts from
python:3.11-slim - Installs all Python dependencies
- Exposes port
8000 - Sets
PENSIEVE_HOST=0.0.0.0andPENSIEVE_PORT=8000 - Runs the
pensievecommand on startup
Build the Frontend Image
docker build -t pensieve-frontend ./frontend
This uses frontend/Dockerfile. The image:
- Builds the React app with Node.js 22
- Serves the static files via nginx on port
80
Run the Backend
docker run -d \
--name pensieve-backend \
-p 8000:8000 \
-e OPENAI_API_KEY=sk-your-openai-api-key \
-e SEARCH_API_KEY=tvly-your-tavily-api-key \
-v $(pwd)/config.yaml:/app/config.yaml:ro \
-v $(pwd)/workspaces:/app/workspaces \
pensieve-backend
Run the Frontend
docker run -d \
--name pensieve-frontend \
-p 3000:80 \
pensieve-frontend
Volume Mounts
| Mount | Container path | Purpose |
|---|---|---|
config.yaml |
/app/config.yaml |
Global configuration — LLM providers, search, server settings |
workspaces/ |
/app/workspaces |
Persistent workspace data — projects, memory, per-workspace config |
The config.yaml mount is read-only (:ro) since the server only reads it at startup. The workspaces directory must be writable because the backend creates workspace and project data at runtime.
Tip: If you don’t mount a
config.yaml, the backend will use its built-in defaults. You still need to provideOPENAI_API_KEYvia environment variable. See Global Configuration for all options.
Environment Variables
Pass environment variables to the backend container with -e:
docker run -d \
-e OPENAI_API_KEY=sk-... \
-e SEARCH_API_KEY=tvly-... \
-e PENSIEVE_HOST=0.0.0.0 \
-e PENSIEVE_PORT=8000 \
-e PENSIEVE_CONFIG=/app/config.yaml \
ghcr.io/5000k/pensieve-backend:latest
See the full Environment Variables reference for all available variables.
Customizing the Frontend API URL
The frontend Docker image supports runtime configuration of the backend URL — no rebuild required. Pass VITE_API_URL and VITE_WS_URL as environment variables when starting the container:
docker run -d \
--name pensieve-frontend \
-p 3000:80 \
-e VITE_API_URL=http://your-backend-host:8000 \
-e VITE_WS_URL=ws://your-backend-host:8000/ws \
ghcr.io/5000k/pensieve-frontend:latest
At startup, the container’s entrypoint script writes these values into /usr/share/nginx/html/env-config.js, which the frontend reads before falling back to build-time defaults. If neither variable is set, the frontend falls back to http://localhost:8000 (HTTP) and ws://localhost:8000/ws (WebSocket).
Tip: This works with both the pre-built GHCR images and images you build from source — no image rebuild is needed to point the frontend at a different backend.
Build-time alternative
If you prefer to bake the URLs into the image at build time (for example, to avoid passing environment variables on every docker run), you can also pass them as build arguments:
cd frontend
docker build \
--build-arg VITE_API_URL=http://your-backend-host:8000 \
--build-arg VITE_WS_URL=ws://your-backend-host:8000/ws \
-t pensieve-frontend .
Note: Runtime environment variables take precedence over build-time values, so you can always override a baked-in URL at container start.
Managing Containers
# View running containers
docker ps
# View logs
docker logs pensieve-backend
docker logs pensieve-frontend
# Stop containers
docker stop pensieve-backend pensieve-frontend
# Remove containers
docker rm pensieve-backend pensieve-frontend
Health Check
Verify the backend is running:
curl http://localhost:8000/health
# → {"status":"ok"}
Next Steps
- Docker Compose — simplify multi-container setup
- Global Configuration — configure LLM providers and search
- Workspace Configuration — customize the pipeline
- Environment Variables — full environment variable reference