Verified each documented command, path, port and env var against what the code actually does, and corrected the drift. Phone App. Was still titled Car Control. The navigation description was also stale: the app moved to a RootShell bottom nav (Garage, Charging, Settings, and Users for admins), so the Settings gear and admin action the dashboard bullet described no longer exist. Adds the Charging screen, noting its public tab is placeholder data and only the Home tab's OCPP control is real, and rebuilds the lib/ tree, which had lost i18n.dart, theme.dart, widgets/ and three screens. Web App. Node 18+ was wrong. The installed Vite is 8.1.2, whose engines field is ^20.19.0 || >=22.12.0 - Node 18 is EOL and cannot build this. API Server. The config table gained OCPP_REQUIRE_TLS, OCPP_PUBLIC_URL, PB_BOOTSTRAP and DRIVERVAULT_SUPERADMIN_*, plus a note that PLUGINS_FILE and the panel-written .env resolve against the working directory (a volume, in Docker). Plugins. Per-tenant credentials sat under "not yet implemented", but /api/integrations/* has done exactly that for both built-ins for a while. Narrowed the roadmap item to the genuinely missing generic version. New Docker/README.md and Docker AIO/README.md: the root README's component table linked those directories as documentation but neither had any. The root README now points at them. All 8 markdown files pass a relative-link check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.6 KiB
DriverVault — Docker AIO (all-in-one image)
PocketBase + API Server + Web App in a single container, supervised by
supervisord with nginx serving the SPA and proxying /api/ to the API Server
on localhost. One image, one volume set, no compose network — the simplest way
to stand DriverVault up on a single host.
Prefer the three-container stack in ../Docker when you want to
scale, upgrade or restart the pieces independently.
:80 nginx ─► SPA, and /api/ ─► API Server on 127.0.0.1:8080 ─► PocketBase on :8070
| File | Use |
|---|---|
Dockerfile |
the all-in-one image (build context must be the repo root) |
docker-compose.yml |
builds from source — for development and local testing |
docker-compose.prod.yml |
pulls the prebuilt image from the registry |
.env.example / .env.prod.example |
copy to .env for the matching compose file |
Run it
cd "Docker AIO"
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/_/.
Note the port mapping: inside the container the web app is on 80, published
as WEB_PORT (8090 by default) to line up with the other deployment.
Building by hand
The build context must be the repo root so the Dockerfile can reach both
API Server/ and Web App/:
docker build -f "Docker AIO/Dockerfile" -t drivervault-aio .
Build args: VITE_API_BASE (leave empty so the bundle uses same-origin /api)
and PB_VERSION (pin PocketBase, or leave empty to fetch the latest release at
build time).
First boot
Identical to the multi-container stack, and idempotent:
- PocketBase upserts its superuser from
PB_ADMIN_EMAIL/PB_ADMIN_PASSWORD. - The API Server waits for PocketBase to report healthy, then creates any
missing collections, reconciles existing ones, and creates the first app
superadminfromDRIVERVAULT_SUPERADMIN_EMAIL/_PASSWORD. SetPB_BOOTSTRAP=falseto skip once the database is established.
Volumes
| Volume | Holds |
|---|---|
/pb/pb_data |
the PocketBase SQLite database and uploaded files |
/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; set PB_DATA / API_DATA to
absolute host paths in the prod file for bind mounts.
Charger control (OCPP)
Chargers in own/proxy mode dial in to /ocpp/{serial} on the API Server port
(8080) — not through nginx — authenticating with a per-charger control token
in an OCPP Basic-auth header. Because a plaintext ws:// would expose that
token, OCPP_REQUIRE_TLS defaults to true.
This image serves plain HTTP, so charger control needs TLS terminated in front
of it, with OCPP_PUBLIC_URL set to the public wss:// base. Only drop
OCPP_REQUIRE_TLS on a trusted network.
Caveats
- Everything runs as root in one container, and a crash of
supervisordtakes all three services down together. That is the trade for the simplicity. - Logs from all three processes are interleaved on the container's stdout/stderr
(
docker logs drivervault-aio). PB_VERSIONempty means the image pulls whatever PocketBase release is latest at build time, so two builds of the same source can differ. Pin it for reproducibility.