Docker Setup

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

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:8000 by default. To use a different backend address, pass VITE_API_URL and VITE_WS_URL at 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.0 and PENSIEVE_PORT=8000
  • Runs the pensieve command 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 provide OPENAI_API_KEY via 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