Files
DriverVault/Docker/docker-compose.yml
T
tajniak81andClaude Opus 5 9258532952 Docker: give the panel's settings screens a permanent home in .env
ee4ac44 removed the api_data volume, which left the panel's Settings ->
PocketBase and Settings -> Web App screens with nowhere to persist to: they
apply at runtime and the container environment wins again on restart. That
is only acceptable if the environment is actually reachable by an operator,
and for two of those keys it was not - WEBAPP_URL was hardcoded in all four
compose files, and POCKETBASE_URL in the two multi-container ones, so
there was no supported way to change them at all.

Both are now ${VAR:-default} with the previous hardcoded value as the
default, so nothing moves for an existing .env while the keys become
settable. CORS_ALLOW_ORIGINS and the admin credentials already were.

The env examples grow a section naming every setting the panel can also
change, saying plainly that the panel's version lasts only for the life of
the container, and giving the commented-out line to make it stick. It also
records the trap in WEBAPP_URL: it is a container-to-container call, so it
has to be reachable from the API Server rather than from a browser, which
is why the default is a service name and not localhost. POCKETBASE_URL is
described as repointable in the multi-container stack and left alone in the
AIO image, where it addresses that container's own PocketBase.

Also dropped two leftovers from when there were two volumes: the storage
sections still said "either".

Checked by parsing all five compose files and asserting each interpolation
default matches the value it replaced, so this cannot have moved a default
by accident. go build and go test ./... still pass (untouched here). Not
verified: no Docker CLI, so no `docker compose config` render and no build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 18:38:48 +02:00

121 lines
5.2 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. Override
# POCKETBASE_URL in .env to point the API Server at a database outside
# this stack — that is also how you make a retarget done from the panel
# permanent, since the panel's change lasts only for the container's life.
POCKETBASE_URL: "${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 the default is the service name — plain
# localhost:8090 would resolve to this container itself. Override
# WEBAPP_URL in .env to make a change from the panel's Web App screen
# permanent; the panel alone only holds it for the container's life.
WEBAPP_URL: "${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 collections or fields the
# server needs, and a stack that skips it never gets them. The API Server
# self-heals exactly one thing — app_settings, the collection holding the
# plugin settings, which it creates on demand because it cannot serve the
# plugin panel without it. Every other schema change still depends on this
# flag. Turn it off only for a database you know 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"
# No volume: the API Server keeps no state on disk — every setting it owns,
# plugin settings included, lives in PocketBase under pb_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: