Every deployment file advised setting PB_BOOTSTRAP=false "once the database
is established". That was harmless while the schema was static. It stopped
being harmless in 9bd5c52, which moved the plugin settings into a new
app_settings collection: a stack upgraded with the bootstrap off never gets
that collection, and a missing collection is deliberately read as "the
database is not ready" rather than "no plugins configured" - so the plugin
panel answers 503 indefinitely and the background retry spins forever.
Fixing the advice rather than the reading: treating a missing collection as
empty would let the first save write a fresh document over settings the
server had simply failed to find, which is the failure this whole line of
work exists to prevent.
So all four compose files, all four .env examples, both stack READMEs and
the AIO Dockerfile now say to leave the bootstrap on, including across
upgrades, and name the symptom an operator would otherwise have to guess
at. Turning it off is still supported, but framed as something to do only
for a database known to match the running release.
Compose files still parse as YAML; go build, go vet and go test ./... pass
(untouched by this commit - it is comments and docs only). Note that this
is guidance, not a guard: an operator who sets PB_BOOTSTRAP=false anyway
still ends up in the same place, and the server would have to re-run the
bootstrap when it finds the collection missing to make that impossible.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
120 lines
4.9 KiB
YAML
120 lines
4.9 KiB
YAML
name: drivervault
|
|
|
|
# Full DriverVault stack: PocketBase (database) + API Server + Web App.
|
|
# Traffic flow (browser): Web App BFF --/api--> API Server --> PocketBase.
|
|
# Copy .env.example to .env and fill in the secrets before `docker compose up`.
|
|
|
|
services:
|
|
pocketbase:
|
|
build:
|
|
context: ./pocketbase
|
|
image: drivervault-pocketbase
|
|
container_name: drivervault-pocketbase
|
|
restart: unless-stopped
|
|
environment:
|
|
# Superuser is created/updated on boot so the API Server can authenticate.
|
|
PB_ADMIN_EMAIL: "${PB_ADMIN_EMAIL:?set PB_ADMIN_EMAIL in .env}"
|
|
PB_ADMIN_PASSWORD: "${PB_ADMIN_PASSWORD:?set PB_ADMIN_PASSWORD in .env}"
|
|
volumes:
|
|
- pb_data:/pb/pb_data
|
|
ports:
|
|
# Admin UI / API exposed on the host for management (http://host:8070/_/).
|
|
- "${PB_PORT:-8070}:8070"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8070/api/health || exit 1"]
|
|
interval: 10s
|
|
timeout: 3s
|
|
retries: 12
|
|
start_period: 10s
|
|
|
|
api-server:
|
|
build:
|
|
context: ../API Server
|
|
image: drivervault-api
|
|
container_name: drivervault-api
|
|
restart: unless-stopped
|
|
depends_on:
|
|
pocketbase:
|
|
condition: service_healthy
|
|
environment:
|
|
API_ADDR: ":8080"
|
|
# Reach PocketBase by its service name on the internal network.
|
|
POCKETBASE_URL: "http://pocketbase:8070"
|
|
POCKETBASE_ADMIN_EMAIL: "${PB_ADMIN_EMAIL}"
|
|
POCKETBASE_ADMIN_PASSWORD: "${PB_ADMIN_PASSWORD}"
|
|
# Probed by the panel status page. This is a server-to-server call inside
|
|
# the compose network, so it must be the service name — the default
|
|
# (localhost:8090) would resolve to this container itself.
|
|
WEBAPP_URL: "http://web-app:8090"
|
|
# Same-origin requests go through the Web App BFF, so CORS is only needed
|
|
# if the browser ever calls the API Server directly. Default to the web origin.
|
|
CORS_ALLOW_ORIGINS: "${CORS_ALLOW_ORIGINS:-http://localhost:8090}"
|
|
AUTH_USERS_COLLECTION: "${AUTH_USERS_COLLECTION:-users}"
|
|
# Schema + super-admin bootstrap (idempotent). Without the SUPERADMIN vars
|
|
# the collections are still created but no app user is, leaving a stack
|
|
# you cannot log into.
|
|
#
|
|
# Leave the bootstrap ON. A release can add a collection the server needs —
|
|
# app_settings, holding the plugin settings, is one — and a stack that
|
|
# skipped it never gets that collection: the plugin panel then answers 503
|
|
# forever, because a missing collection is read as "database not ready",
|
|
# never as "no plugins configured". Turn it off only for a database you
|
|
# know already matches the release.
|
|
PB_BOOTSTRAP: "${PB_BOOTSTRAP:-true}"
|
|
DRIVERVAULT_SUPERADMIN_EMAIL: "${DRIVERVAULT_SUPERADMIN_EMAIL:-}"
|
|
DRIVERVAULT_SUPERADMIN_PASSWORD: "${DRIVERVAULT_SUPERADMIN_PASSWORD:-}"
|
|
DRIVERVAULT_SUPERADMIN_NAME: "${DRIVERVAULT_SUPERADMIN_NAME:-Administrator}"
|
|
# OCPP charger control (Anker Solix). Chargers are rejected unless they
|
|
# connect over TLS; set OCPP_REQUIRE_TLS=false in .env only when TLS is
|
|
# terminated in front of this stack or for local dev on a trusted network.
|
|
OCPP_REQUIRE_TLS: "${OCPP_REQUIRE_TLS:-true}"
|
|
OCPP_PUBLIC_URL: "${OCPP_PUBLIC_URL:-}"
|
|
ports:
|
|
# Optional direct access to the API Server (and its panel at /); the Web
|
|
# App reaches it over the internal network, not this host port. Chargers
|
|
# dialling /ocpp/{serial} also arrive here.
|
|
- "${API_PORT:-8080}:8080"
|
|
volumes:
|
|
# The .env the panel writes back when a superadmin retargets PocketBase —
|
|
# see the API Server Dockerfile. Plugin settings live in the database, so
|
|
# they no longer depend on this volume.
|
|
- api_data:/data
|
|
healthcheck:
|
|
# Declared here rather than relying only on the image's HEALTHCHECK, so the
|
|
# depends_on gate below still works against an older pulled image.
|
|
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/healthz || exit 1"]
|
|
interval: 10s
|
|
timeout: 3s
|
|
retries: 12
|
|
start_period: 20s
|
|
|
|
web-app:
|
|
build:
|
|
context: ../Web App
|
|
args:
|
|
# Empty -> bundle uses same-origin "/api", which the BFF proxies below.
|
|
VITE_API_BASE: "${VITE_API_BASE:-}"
|
|
image: drivervault-web
|
|
container_name: drivervault-web
|
|
restart: unless-stopped
|
|
depends_on:
|
|
# The image now ships a HEALTHCHECK, so wait for the API Server to be
|
|
# serving rather than merely started.
|
|
api-server:
|
|
condition: service_healthy
|
|
environment:
|
|
# The BFF reverse-proxies /api/* to the API Server over the internal network.
|
|
API_BASE: "http://api-server:8080"
|
|
ports:
|
|
- "${WEB_PORT:-8090}:8090"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8090/healthz || exit 1"]
|
|
interval: 10s
|
|
timeout: 3s
|
|
retries: 12
|
|
start_period: 10s
|
|
|
|
volumes:
|
|
pb_data:
|
|
api_data:
|