Skip to content

Deploy with Docker

Run Bookhoarder in a container with Docker or Docker Compose.

Updated View as Markdown

Bookhoarder ships as a single container. Object storage is the only persistence layer — no database, no schema, nothing to migrate — so deploying is really just: pick where the books live, then start the container.

Pick a storage backend

Local disk needs nothing extra; S3 or Cloudflare R2 need a bucket and credentials.

Run the container

docker run or docker compose up, with STORAGE_DRIVER and that backend’s env vars set.

Open Bookhoarder

Visit http://localhost:3000 and create your first profile — it becomes the admin.

Prerequisites

  • Docker Engine 24+ (or Docker Desktop), with the Compose plugin if you’re using docker compose
  • A storage backend — local disk needs nothing extra; S3 or Cloudflare R2 need a bucket and a set of credentials

Run the container

Every backend runs through the same image — only the environment variables change. STORAGE_DRIVER selects which one: local (default), or s3 for any S3-compatible store, including Cloudflare R2.

docker run -d \
  --name bookhoard \
  -p 3000:3000 \
  -v bookhoard_data:/app/.data \
  -e STORAGE_DRIVER=local \
  ghcr.io/bookhoard/bookhoarder:latest

The command above uses the local driver — see Local disk for the volume-mount details. For S3 or Cloudflare R2, swap the -e STORAGE_DRIVER=local and -v flags for that backend’s environment variables; the rest of the docker run stays the same.

Or use Docker Compose

For anything past a one-off docker run, put the environment in a docker-compose.yml instead:

docker-compose.ymlyaml
services:
  app:
    image: ghcr.io/bookhoard/bookhoarder:latest
    ports:
      - "3000:3000"
    environment:
      STORAGE_DRIVER: s3
      S3_ENDPOINT: https://<ACCOUNT_ID>.r2.cloudflarestorage.com
      S3_BUCKET: bookhoard
      S3_ACCESS_KEY: <YOUR_ACCESS_KEY>
      S3_SECRET_KEY: <YOUR_SECRET_KEY>
    restart: unless-stopped

Swap the environment: block for whichever backend you picked — add a volumes: entry instead if you’re using the local driver.

docker compose up -d

Health checks

The container exposes GET /api/health, which checks connectivity to the configured storage backend and returns 200 {"status":"ok"} or 503 {"status":"error", "message": "..."}. Wire it into Compose or your orchestrator:

healthcheck:
  test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"]
  interval: 30s
  timeout: 5s
  retries: 3

Open Bookhoarder

Visit http://localhost:3000. The first profile you create becomes an admin; additional profiles can be added from settings, with optional per-profile passwords.

Environment reference

Variable Default Notes
STORAGE_DRIVER local local or s3 — see Storage for backend-specific vars
SMTP_URL Enables send-to-e-reader
OPENLIBRARY_CONTACT Email or contact URL for metadata/cover lookups
Navigation

Type to search…

↑↓ navigate↵ selectEsc close