Files
DriverVault/Docker/README.md
T
tajniak81andClaude Opus 5 9487de84b0 Docker AIO: a folder name without a space in it
The all-in-one folder is now Docker-AIO, so -f Docker-AIO/Dockerfile
resolves without quoting. Every path that pointed at the old name
follows it: the compose build stanza, the documented build commands,
and the links from the two READMEs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 20:01:19 +02:00

3.9 KiB

DriverVault — Docker (multi-container stack)

Three containers — PocketBase, API Server, Web App — on one compose network. This is the deployment to use unless you specifically want everything in a single image; for that see ../Docker-AIO.

Browser ─► Web App BFF (:8090) ──/api/*──► API Server (:8080) ─► PocketBase (:8070)

Only the Web App port is meant to be public. The API Server and the PocketBase admin UI are published for convenience and, in the prod file, bound to 127.0.0.1 by default.

File Use
docker-compose.yml builds from source in this repo — for development and local testing
docker-compose.prod.yml pulls prebuilt images from the registry — for deployment
.env.example / .env.prod.example copy to .env for the matching compose file
pocketbase/ the PocketBase image (official release binary on alpine)

Run it

cd Docker
cp .env.example .env        # then edit — PB_ADMIN_* have no safe defaults
docker compose up -d --build

Production, from the registry:

cp .env.prod.example .env   # then edit
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d

Then: web app on http://host:8090/, the API Server's superadmin panel on http://host:8080/, PocketBase admin on http://host:8070/_/.

First boot

Both steps are idempotent, so restarts and upgrades are safe:

  1. PocketBase upserts its superuser from PB_ADMIN_EMAIL / PB_ADMIN_PASSWORD. This is the only way to create the first superuser — the REST API cannot bootstrap it. The API Server then authenticates with the same credentials.
  2. The API Server creates any missing collections and reconciles existing ones, then creates the first app superadmin from DRIVERVAULT_SUPERADMIN_EMAIL / _PASSWORD if no such user exists. Set PB_BOOTSTRAP=false to skip once the database is established.

No manual setup-pocketbase.mjs step is needed here — the server runs the same schema reconcile itself.

Volumes

Volume Holds
pb_data the PocketBase SQLite database and uploaded files
api_data the API Server's plugins.json, and the .env the panel rewrites when a superadmin retargets the PocketBase connection

Both default to Docker-managed named volumes. In the prod file, set PB_DATA / API_DATA to absolute host paths for bind mounts instead.

The API Server container runs as an unprivileged user, and a named volume inherits that ownership from the image. A bind mount does not — the host directory's ownership wins, so chown it to the container's app user (or chmod it writable) before setting API_DATA to a host path, otherwise the server cannot write plugins.json.

Charger control (OCPP)

Chargers in own/proxy mode dial in to /ocpp/{serial} on the API Server port, authenticating with a per-charger control token in an OCPP Basic-auth header. A plaintext ws:// would put that token on the wire in the clear, so OCPP_REQUIRE_TLS defaults to true and non-TLS connections are rejected.

This stack serves plain HTTP, so to actually use charger control you need to terminate TLS in a reverse proxy in front of it and set OCPP_PUBLIC_URL to the public wss:// base (behind a proxy, deriving it from request headers is unreliable). OCPP_REQUIRE_TLS=false is for trusted networks only. You will also need API_BIND set so the proxy can reach the port.

Notes

  • docker-compose.yml builds the API Server and Web App from ../API Server and ../Web App, so run it from this directory with the repo checked out.
  • The Web App's Vue bundle is built with an empty VITE_API_BASE, so the browser uses same-origin /api and the BFF proxies it — no CORS in play.
  • CORS_ALLOW_ORIGINS therefore only matters if a browser calls the API Server directly. Native mobile apps are not subject to CORS at all.