Bring the Docker setup in line with DriverVault's
The combined stack now includes PocketBase as a first-class service instead of assuming an external one: a Docker/pocketbase image built from the release binary that bundles the pb_migrations and upserts the superuser on boot, so a fresh stack checks/creates its collections and super-admin the same way DriverVault does. Add production compose variants (registry images) and .env(.prod).example files for both Docker/ and Docker AIO/, a top-level compose name, a PocketBase healthcheck with a service_healthy dependency, and env-driven ports. Move the containerized PocketBase to :8070 (the live remote PB stays 10.2.1.10:8026). Add a root .dockerignore to trim the repo-root build context used by the pocketbase and AIO images. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
11fb1e060d
commit
2d20f6f29c
@@ -0,0 +1,27 @@
|
|||||||
|
# Root build-context ignore. The pocketbase and Docker AIO images build with the
|
||||||
|
# repo root as their context (they COPY from "API Server/" and "Web App/"), so
|
||||||
|
# keep the context lean: only those two trees plus Docker/pocketbase are needed.
|
||||||
|
|
||||||
|
# Sibling apps unrelated to the server images.
|
||||||
|
Adobe Plugin/
|
||||||
|
Design/
|
||||||
|
Fly App/
|
||||||
|
Phone App/
|
||||||
|
|
||||||
|
# Frontend deps + generated bundles — rebuilt inside the images.
|
||||||
|
**/node_modules/
|
||||||
|
**/dist/
|
||||||
|
|
||||||
|
# Secrets & local build artifacts — never send to the build context.
|
||||||
|
**/.env
|
||||||
|
plugins.json
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# VCS / editor / tooling noise.
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.claude/
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Copy to .env and fill in. Used by the Docker AIO docker-compose.yml.
|
||||||
|
|
||||||
|
# --- PocketBase superuser (also used by the API Server to authenticate) ------
|
||||||
|
POCKETBASE_ADMIN_EMAIL=admin@dji.local
|
||||||
|
POCKETBASE_ADMIN_PASSWORD=djiadmin2026!
|
||||||
|
|
||||||
|
# The app super-admin login (superadmin@pilotvault.local) is created by the
|
||||||
|
# bundled PocketBase migrations on first boot.
|
||||||
|
|
||||||
|
# Allowed CORS origin(s) — "*" is convenient for a local demo.
|
||||||
|
CORS_ALLOW_ORIGINS=*
|
||||||
|
|
||||||
|
# --- Host port mappings (optional; defaults shown) --------------------------
|
||||||
|
WEB_PORT=8090
|
||||||
|
API_PORT=8080
|
||||||
|
PB_PORT=8070
|
||||||
|
|
||||||
|
# --- Storage ----------------------------------------------------------------
|
||||||
|
# Docker-managed named volume by default; set PB_DATA to an absolute host path
|
||||||
|
# for a bind mount, e.g. PB_DATA=/srv/pilotvault/pb_data
|
||||||
|
PB_DATA=pb_data
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# PilotVault all-in-one — production config.
|
||||||
|
# Copy to .env and fill in, then:
|
||||||
|
# docker compose -f docker-compose.prod.yml pull
|
||||||
|
# docker compose -f docker-compose.prod.yml up -d
|
||||||
|
|
||||||
|
# --- Registry image ---------------------------------------------------------
|
||||||
|
AIO_IMAGE=10.2.1.10:5500/admin/pilotvault-aio:latest
|
||||||
|
|
||||||
|
# --- PocketBase superuser (required) ----------------------------------------
|
||||||
|
# Created/updated on first boot. The API Server uses these to manage the database.
|
||||||
|
POCKETBASE_ADMIN_EMAIL=admin@dji.local
|
||||||
|
POCKETBASE_ADMIN_PASSWORD=change-me-long-password
|
||||||
|
|
||||||
|
# The app super-admin login (superadmin@pilotvault.local) is created by the
|
||||||
|
# bundled PocketBase migrations on first boot.
|
||||||
|
|
||||||
|
# Allowed CORS origin(s) — match your public web URL / WEB_PORT.
|
||||||
|
CORS_ALLOW_ORIGINS=http://localhost:8090
|
||||||
|
|
||||||
|
# --- Host port mappings (optional; defaults shown) --------------------------
|
||||||
|
WEB_PORT=8090
|
||||||
|
API_PORT=8080
|
||||||
|
PB_PORT=8070
|
||||||
|
|
||||||
|
# --- Storage ----------------------------------------------------------------
|
||||||
|
# Default is a Docker-managed named volume ("pb_data"). Set PB_DATA to an
|
||||||
|
# absolute host path for a bind mount, e.g. PB_DATA=/srv/pilotvault/pb_data
|
||||||
|
PB_DATA=pb_data
|
||||||
@@ -8,10 +8,10 @@
|
|||||||
# and "Web App/"). From E:\VS Code Projects\PilotVault run:
|
# and "Web App/"). From E:\VS Code Projects\PilotVault run:
|
||||||
#
|
#
|
||||||
# docker build -f "Docker AIO/Dockerfile" -t pilotvault-aio .
|
# docker build -f "Docker AIO/Dockerfile" -t pilotvault-aio .
|
||||||
# docker run -p 8090:8090 -p 8080:8080 -p 8026:8026 \
|
# docker run -p 8090:8090 -p 8080:8080 -p 8070:8070 \
|
||||||
# -v pilotvault_pb:/pb/pb_data pilotvault-aio
|
# -v pilotvault_pb:/pb/pb_data pilotvault-aio
|
||||||
#
|
#
|
||||||
# Internal ports (loopback-wired): PocketBase 8026, API Server 8080, Web App 8090.
|
# Internal ports (loopback-wired): PocketBase 8070, API Server 8080, Web App 8090.
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Stage 1 — build the API Server's embedded Vue panel (-> internal/api/dist)
|
# Stage 1 — build the API Server's embedded Vue panel (-> internal/api/dist)
|
||||||
@@ -91,7 +91,7 @@ COPY ["API Server/pocketbase/pb_migrations/", "/pb/pb_migrations/"]
|
|||||||
# Web App reads ADDR / API_BASE
|
# Web App reads ADDR / API_BASE
|
||||||
# NOTE: these bundle default credentials for convenience — override at `docker run`.
|
# NOTE: these bundle default credentials for convenience — override at `docker run`.
|
||||||
ENV API_ADDR=":8080" \
|
ENV API_ADDR=":8080" \
|
||||||
POCKETBASE_URL="http://127.0.0.1:8026" \
|
POCKETBASE_URL="http://127.0.0.1:8070" \
|
||||||
CORS_ALLOW_ORIGINS="*" \
|
CORS_ALLOW_ORIGINS="*" \
|
||||||
POCKETBASE_ADMIN_EMAIL="admin@dji.local" \
|
POCKETBASE_ADMIN_EMAIL="admin@dji.local" \
|
||||||
POCKETBASE_ADMIN_PASSWORD="djiadmin2026!" \
|
POCKETBASE_ADMIN_PASSWORD="djiadmin2026!" \
|
||||||
@@ -111,7 +111,7 @@ pidfile=/run/supervisord.pid
|
|||||||
priority=10
|
priority=10
|
||||||
directory=/pb
|
directory=/pb
|
||||||
# Ensure the service-account superuser exists, then serve on the internal port.
|
# Ensure the service-account superuser exists, then serve on the internal port.
|
||||||
command=/bin/sh -c "/app/pocketbase superuser upsert \"$POCKETBASE_ADMIN_EMAIL\" \"$POCKETBASE_ADMIN_PASSWORD\" --dir=/pb/pb_data ; exec /app/pocketbase serve --http=0.0.0.0:8026 --dir=/pb/pb_data --migrationsDir=/pb/pb_migrations"
|
command=/bin/sh -c "/app/pocketbase superuser upsert \"$POCKETBASE_ADMIN_EMAIL\" \"$POCKETBASE_ADMIN_PASSWORD\" --dir=/pb/pb_data ; exec /app/pocketbase serve --http=0.0.0.0:8070 --dir=/pb/pb_data --migrationsDir=/pb/pb_migrations"
|
||||||
autorestart=true
|
autorestart=true
|
||||||
startsecs=3
|
startsecs=3
|
||||||
stdout_logfile=/dev/stdout
|
stdout_logfile=/dev/stdout
|
||||||
@@ -145,6 +145,6 @@ EOF
|
|||||||
# PocketBase data (SQLite). Mount a volume here to persist across restarts.
|
# PocketBase data (SQLite). Mount a volume here to persist across restarts.
|
||||||
VOLUME ["/pb/pb_data"]
|
VOLUME ["/pb/pb_data"]
|
||||||
|
|
||||||
EXPOSE 8090 8080 8026
|
EXPOSE 8090 8080 8070
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
ENTRYPOINT ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
name: pilotvault-aio
|
||||||
|
|
||||||
|
# Production all-in-one — pulls the prebuilt image from the registry instead of
|
||||||
|
# building. One container runs PocketBase + API Server + Web App. Everything an
|
||||||
|
# operator needs to set lives in .env.
|
||||||
|
#
|
||||||
|
# 1. cp .env.prod.example .env (then edit it)
|
||||||
|
# 2. docker compose -f docker-compose.prod.yml pull
|
||||||
|
# 3. docker compose -f docker-compose.prod.yml up -d
|
||||||
|
#
|
||||||
|
# On first boot the bundled PocketBase upserts its superuser from
|
||||||
|
# POCKETBASE_ADMIN_* and runs the JS migrations, which create/reconcile every
|
||||||
|
# collection and seed the baseline org + accounts (incl. superadmin@pilotvault.local).
|
||||||
|
# Idempotent, so restarts and upgrades are safe.
|
||||||
|
|
||||||
|
services:
|
||||||
|
pilotvault:
|
||||||
|
image: "${AIO_IMAGE:-10.2.1.10:5500/admin/pilotvault-aio:latest}"
|
||||||
|
container_name: pilotvault-aio
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POCKETBASE_ADMIN_EMAIL: "${POCKETBASE_ADMIN_EMAIL:?set POCKETBASE_ADMIN_EMAIL in .env}"
|
||||||
|
POCKETBASE_ADMIN_PASSWORD: "${POCKETBASE_ADMIN_PASSWORD:?set POCKETBASE_ADMIN_PASSWORD in .env}"
|
||||||
|
CORS_ALLOW_ORIGINS: "${CORS_ALLOW_ORIGINS:-http://localhost:8090}"
|
||||||
|
ports:
|
||||||
|
- "${WEB_PORT:-8090}:8090" # Web App (control panel)
|
||||||
|
- "${API_PORT:-8080}:8080" # API Server + embedded API web panel (root /)
|
||||||
|
- "${PB_PORT:-8070}:8070" # PocketBase admin UI / API
|
||||||
|
volumes:
|
||||||
|
# Named volume by default; set PB_DATA to a host path in .env for a bind mount.
|
||||||
|
- "${PB_DATA:-pb_data}:/pb/pb_data"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pb_data:
|
||||||
@@ -1,7 +1,17 @@
|
|||||||
|
name: pilotvault-aio
|
||||||
|
|
||||||
# All-in-one PilotVault stack (PocketBase + API Server + Web App) in ONE container.
|
# All-in-one PilotVault stack (PocketBase + API Server + Web App) in ONE container.
|
||||||
# Run from this Docker AIO/ folder: docker compose up --build
|
# Run from this Docker AIO/ folder:
|
||||||
|
#
|
||||||
|
# cp .env.example .env # then edit the credentials/ports
|
||||||
|
# docker compose up --build
|
||||||
|
#
|
||||||
# The build context is the repo root (..) because the Dockerfile COPYs from
|
# The build context is the repo root (..) because the Dockerfile COPYs from
|
||||||
# "API Server/" and "Web App/".
|
# "API Server/" and "Web App/".
|
||||||
|
#
|
||||||
|
# On first boot the bundled PocketBase upserts its superuser from
|
||||||
|
# POCKETBASE_ADMIN_* and runs the JS migrations, which create/reconcile every
|
||||||
|
# collection and seed the baseline org + accounts (incl. superadmin@pilotvault.local).
|
||||||
|
|
||||||
services:
|
services:
|
||||||
pilotvault:
|
pilotvault:
|
||||||
@@ -13,19 +23,20 @@ services:
|
|||||||
# PB_ARCH: "amd64" # use "arm64" on Apple Silicon
|
# PB_ARCH: "amd64" # use "arm64" on Apple Silicon
|
||||||
image: pilotvault-aio
|
image: pilotvault-aio
|
||||||
container_name: pilotvault-aio
|
container_name: pilotvault-aio
|
||||||
ports:
|
restart: unless-stopped
|
||||||
- "8090:8090" # Web App (control panel)
|
|
||||||
- "8080:8080" # API Server
|
|
||||||
- "8026:8026" # PocketBase
|
|
||||||
environment:
|
environment:
|
||||||
# Loopback-wired between the three in-container services. Override the
|
# Loopback-wired between the three in-container services. Override the
|
||||||
# bundled default credentials here for anything real.
|
# bundled default credentials here for anything real.
|
||||||
POCKETBASE_ADMIN_EMAIL: "admin@dji.local"
|
POCKETBASE_ADMIN_EMAIL: "${POCKETBASE_ADMIN_EMAIL:-admin@dji.local}"
|
||||||
POCKETBASE_ADMIN_PASSWORD: "djiadmin2026!"
|
POCKETBASE_ADMIN_PASSWORD: "${POCKETBASE_ADMIN_PASSWORD:-djiadmin2026!}"
|
||||||
CORS_ALLOW_ORIGINS: "*"
|
CORS_ALLOW_ORIGINS: "${CORS_ALLOW_ORIGINS:-*}"
|
||||||
|
ports:
|
||||||
|
- "${WEB_PORT:-8090}:8090" # Web App (control panel)
|
||||||
|
- "${API_PORT:-8080}:8080" # API Server
|
||||||
|
- "${PB_PORT:-8070}:8070" # PocketBase admin UI / API
|
||||||
volumes:
|
volumes:
|
||||||
- pb_data:/pb/pb_data # persist PocketBase SQLite across restarts
|
# Named volume by default; set PB_DATA to a host path in .env for a bind mount.
|
||||||
restart: unless-stopped
|
- "${PB_DATA:-pb_data}:/pb/pb_data"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pb_data:
|
pb_data:
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Copy to .env and fill in. Used by the combined docker-compose.yml (build & run).
|
||||||
|
|
||||||
|
# --- PocketBase superuser (also used by the API Server to authenticate) ------
|
||||||
|
# Created/updated on the PocketBase container's first boot. REQUIRED.
|
||||||
|
POCKETBASE_ADMIN_EMAIL=admin@dji.local
|
||||||
|
POCKETBASE_ADMIN_PASSWORD=change-me-long-password
|
||||||
|
|
||||||
|
# The app super-admin login (superadmin@pilotvault.local) is created by the
|
||||||
|
# bundled PocketBase migrations on first boot — no separate env var needed.
|
||||||
|
|
||||||
|
# --- API Server -------------------------------------------------------------
|
||||||
|
# Allowed CORS origin(s) for the web app (match WEB_PORT / your public URL).
|
||||||
|
# Native apps are not subject to CORS.
|
||||||
|
CORS_ALLOW_ORIGINS=http://localhost:8090
|
||||||
|
|
||||||
|
# --- Host port mappings (optional; defaults shown) --------------------------
|
||||||
|
PB_PORT=8070
|
||||||
|
API_PORT=8080
|
||||||
|
WEB_PORT=8090
|
||||||
|
|
||||||
|
# --- Storage ----------------------------------------------------------------
|
||||||
|
# Docker-managed named volume by default; set PB_DATA to an absolute host path
|
||||||
|
# for a bind mount, e.g. PB_DATA=/srv/pilotvault/pb_data
|
||||||
|
PB_DATA=pb_data
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# PilotVault — production stack config.
|
||||||
|
# Copy to .env and fill in, then:
|
||||||
|
# docker compose -f docker-compose.prod.yml pull
|
||||||
|
# docker compose -f docker-compose.prod.yml up -d
|
||||||
|
|
||||||
|
# --- Registry images --------------------------------------------------------
|
||||||
|
# Defaults point at the internal registry; override to pin a tag or use a mirror.
|
||||||
|
PB_IMAGE=10.2.1.10:5500/admin/pilotvault-pocketbase:latest
|
||||||
|
API_IMAGE=10.2.1.10:5500/admin/pilotvault-api-server:latest
|
||||||
|
WEB_IMAGE=10.2.1.10:5500/admin/pilotvault-web-app:latest
|
||||||
|
|
||||||
|
# --- PocketBase superuser (required) ----------------------------------------
|
||||||
|
# Created/updated on the PocketBase container's first boot. The API Server uses
|
||||||
|
# these same credentials to manage the database.
|
||||||
|
POCKETBASE_ADMIN_EMAIL=admin@dji.local
|
||||||
|
POCKETBASE_ADMIN_PASSWORD=change-me-long-password
|
||||||
|
|
||||||
|
# The app super-admin login (superadmin@pilotvault.local) is created by the
|
||||||
|
# bundled PocketBase migrations on first boot — distinct from the superuser above.
|
||||||
|
|
||||||
|
# --- API Server -------------------------------------------------------------
|
||||||
|
# Allowed CORS origin(s) for the web app (match your public URL / WEB_PORT).
|
||||||
|
CORS_ALLOW_ORIGINS=http://localhost:8090
|
||||||
|
|
||||||
|
# --- Ports ------------------------------------------------------------------
|
||||||
|
# WEB_PORT is the public front door (bound on all interfaces).
|
||||||
|
WEB_PORT=8090
|
||||||
|
# PocketBase admin UI and the API panel are bound to localhost only by default.
|
||||||
|
# Set PB_BIND / API_BIND to 0.0.0.0 to expose them on the network.
|
||||||
|
PB_PORT=8070
|
||||||
|
PB_BIND=127.0.0.1
|
||||||
|
API_PORT=8080
|
||||||
|
API_BIND=127.0.0.1
|
||||||
|
|
||||||
|
# --- Storage ----------------------------------------------------------------
|
||||||
|
# Default is a Docker-managed named volume ("pb_data"). Set PB_DATA to an
|
||||||
|
# absolute host path for a bind mount, e.g. PB_DATA=/srv/pilotvault/pb_data
|
||||||
|
PB_DATA=pb_data
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
name: pilotvault
|
||||||
|
|
||||||
|
# Production PilotVault stack — pulls prebuilt images from the registry instead of
|
||||||
|
# building from source. Everything an operator needs to set lives in .env.
|
||||||
|
#
|
||||||
|
# 1. cp .env.prod.example .env (then edit — secrets/ports/volumes/images)
|
||||||
|
# 2. docker compose -f docker-compose.prod.yml pull
|
||||||
|
# 3. docker compose -f docker-compose.prod.yml up -d
|
||||||
|
#
|
||||||
|
# Traffic flow (browser): Web App BFF --/api--> API Server --> PocketBase.
|
||||||
|
#
|
||||||
|
# On first boot PocketBase upserts its superuser from POCKETBASE_ADMIN_* and runs
|
||||||
|
# the bundled migrations (create/reconcile collections + seed the baseline org and
|
||||||
|
# the superadmin@pilotvault.local login). Idempotent, so restarts/upgrades are safe.
|
||||||
|
|
||||||
|
services:
|
||||||
|
pocketbase:
|
||||||
|
image: "${PB_IMAGE:-10.2.1.10:5500/admin/pilotvault-pocketbase:latest}"
|
||||||
|
container_name: pilotvault-pocketbase
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POCKETBASE_ADMIN_EMAIL: "${POCKETBASE_ADMIN_EMAIL:?set POCKETBASE_ADMIN_EMAIL in .env}"
|
||||||
|
POCKETBASE_ADMIN_PASSWORD: "${POCKETBASE_ADMIN_PASSWORD:?set POCKETBASE_ADMIN_PASSWORD in .env}"
|
||||||
|
volumes:
|
||||||
|
# Named volume by default; set PB_DATA to a host path in .env for a bind mount.
|
||||||
|
- "${PB_DATA:-pb_data}:/pb/pb_data"
|
||||||
|
ports:
|
||||||
|
# Bound to localhost by default — the admin UI (/_/) is reachable only on the
|
||||||
|
# host. Set PB_BIND=0.0.0.0 in .env to expose it on the network.
|
||||||
|
- "${PB_BIND:-127.0.0.1}:${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:
|
||||||
|
image: "${API_IMAGE:-10.2.1.10:5500/admin/pilotvault-api-server:latest}"
|
||||||
|
container_name: pilotvault-api-server
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
pocketbase:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
API_ADDR: ":8080"
|
||||||
|
POCKETBASE_URL: "http://pocketbase:8070"
|
||||||
|
POCKETBASE_ADMIN_EMAIL: "${POCKETBASE_ADMIN_EMAIL}"
|
||||||
|
POCKETBASE_ADMIN_PASSWORD: "${POCKETBASE_ADMIN_PASSWORD}"
|
||||||
|
CORS_ALLOW_ORIGINS: "${CORS_ALLOW_ORIGINS:-http://localhost:8090}"
|
||||||
|
ports:
|
||||||
|
# Localhost-only by default (the Web App reaches it over the internal
|
||||||
|
# network). Set API_BIND=0.0.0.0 to expose the API panel on the network.
|
||||||
|
- "${API_BIND:-127.0.0.1}:${API_PORT:-8080}:8080"
|
||||||
|
|
||||||
|
web-app:
|
||||||
|
image: "${WEB_IMAGE:-10.2.1.10:5500/admin/pilotvault-web-app:latest}"
|
||||||
|
container_name: pilotvault-web-app
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- api-server
|
||||||
|
environment:
|
||||||
|
ADDR: ":8090"
|
||||||
|
API_BASE: "http://api-server:8080"
|
||||||
|
ports:
|
||||||
|
# The public front door. Bound on all interfaces so browsers can reach it.
|
||||||
|
- "${WEB_PORT:-8090}:8090"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pb_data:
|
||||||
+69
-16
@@ -1,40 +1,93 @@
|
|||||||
# Combined stack: API Server + Web App on a shared network.
|
name: pilotvault
|
||||||
# Run from this Docker/ folder: docker compose up --build
|
|
||||||
# Build contexts point back up to each service directory.
|
# Combined PilotVault stack: PocketBase (database) + API Server + Web App, built
|
||||||
|
# from source on a shared network. Run from this Docker/ folder:
|
||||||
|
#
|
||||||
|
# cp .env.example .env # then edit the secrets/ports
|
||||||
|
# docker compose up --build
|
||||||
|
#
|
||||||
|
# Traffic flow (browser): Web App BFF --/api--> API Server --> PocketBase.
|
||||||
|
#
|
||||||
|
# On first boot PocketBase upserts its superuser from POCKETBASE_ADMIN_* and runs
|
||||||
|
# the bundled JS migrations, which create/reconcile every collection and seed the
|
||||||
|
# baseline org + accounts (including the superadmin@pilotvault.local app login).
|
||||||
|
# Every step is idempotent, so restarts and upgrades are safe.
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
pocketbase:
|
||||||
|
build:
|
||||||
|
# Repo root — the Dockerfile bundles the migrations from "API Server/".
|
||||||
|
context: ..
|
||||||
|
dockerfile: Docker/pocketbase/Dockerfile
|
||||||
|
image: pilotvault-pocketbase
|
||||||
|
container_name: pilotvault-pocketbase
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
# The superuser is created/updated on boot (the API Server authenticates
|
||||||
|
# with it). This is the only place the first superuser can be created — the
|
||||||
|
# REST API cannot bootstrap it.
|
||||||
|
POCKETBASE_ADMIN_EMAIL: "${POCKETBASE_ADMIN_EMAIL:?set POCKETBASE_ADMIN_EMAIL in .env}"
|
||||||
|
POCKETBASE_ADMIN_PASSWORD: "${POCKETBASE_ADMIN_PASSWORD:?set POCKETBASE_ADMIN_PASSWORD in .env}"
|
||||||
|
volumes:
|
||||||
|
# Named volume by default; set PB_DATA to a host path in .env for a bind mount.
|
||||||
|
- "${PB_DATA:-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
|
||||||
|
networks:
|
||||||
|
- pilotvault
|
||||||
|
|
||||||
api-server:
|
api-server:
|
||||||
build:
|
build:
|
||||||
context: "../API Server"
|
context: "../API Server"
|
||||||
image: pilotvault-api-server
|
image: pilotvault-api-server
|
||||||
container_name: pilotvault-api-server
|
container_name: pilotvault-api-server
|
||||||
# Config (POCKETBASE_URL, CORS_ALLOW_ORIGINS, POCKETBASE_ADMIN_*) from .env.
|
restart: unless-stopped
|
||||||
env_file:
|
depends_on:
|
||||||
- "../API Server/.env"
|
pocketbase:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
API_ADDR: ":8080"
|
||||||
|
# Reach PocketBase by its service name on the shared network.
|
||||||
|
POCKETBASE_URL: "http://pocketbase:8070"
|
||||||
|
POCKETBASE_ADMIN_EMAIL: "${POCKETBASE_ADMIN_EMAIL}"
|
||||||
|
POCKETBASE_ADMIN_PASSWORD: "${POCKETBASE_ADMIN_PASSWORD}"
|
||||||
|
# Same-origin requests go through the Web App BFF, so CORS is only needed if
|
||||||
|
# a browser ever calls the API Server directly. Default to the web origin.
|
||||||
|
CORS_ALLOW_ORIGINS: "${CORS_ALLOW_ORIGINS:-http://localhost:8090}"
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
# Optional direct access to the API Server (and its panel at /); the Web App
|
||||||
|
# reaches it over the internal network, not this host port.
|
||||||
|
- "${API_PORT:-8080}:8080"
|
||||||
networks:
|
networks:
|
||||||
- pilotvault
|
- pilotvault
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
web-app:
|
web-app:
|
||||||
build:
|
build:
|
||||||
context: "../Web App"
|
context: "../Web App"
|
||||||
image: pilotvault-web-app
|
image: pilotvault-web-app
|
||||||
container_name: pilotvault-web-app
|
container_name: pilotvault-web-app
|
||||||
environment:
|
restart: unless-stopped
|
||||||
ADDR: ":8090"
|
|
||||||
# Reach the API Server by its service name on the shared network —
|
|
||||||
# no host.docker.internal needed here.
|
|
||||||
API_BASE: "http://api-server:8080"
|
|
||||||
ports:
|
|
||||||
- "8090:8090"
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- api-server
|
- api-server
|
||||||
|
environment:
|
||||||
|
ADDR: ":8090"
|
||||||
|
# The BFF reverse-proxies /api/* to the API Server over the shared network.
|
||||||
|
API_BASE: "http://api-server:8080"
|
||||||
|
ports:
|
||||||
|
- "${WEB_PORT:-8090}:8090"
|
||||||
networks:
|
networks:
|
||||||
- pilotvault
|
- pilotvault
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
pilotvault:
|
pilotvault:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pb_data:
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
#
|
||||||
|
# PocketBase for PilotVault, built from the official release binary on alpine.
|
||||||
|
#
|
||||||
|
# It bundles the JS migrations from "API Server/pocketbase/pb_migrations" so that
|
||||||
|
# on first serve PocketBase creates/reconciles every collection and seeds the
|
||||||
|
# baseline organization + accounts (including the superadmin@pilotvault.local app
|
||||||
|
# login). Together with the `superuser upsert` in the entrypoint, THIS is where
|
||||||
|
# PilotVault "checks" that the schema and the super-admin exist — all idempotent,
|
||||||
|
# so restarts and upgrades are safe.
|
||||||
|
#
|
||||||
|
# BUILD CONTEXT IS THE REPO ROOT (the migrations live under "API Server/"). It is
|
||||||
|
# built for you by Docker/docker-compose.yml; to build it by hand run from
|
||||||
|
# E:\VS Code Projects\PilotVault:
|
||||||
|
#
|
||||||
|
# docker build -f Docker/pocketbase/Dockerfile -t pilotvault-pocketbase .
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# Pin the version to match the rest of PilotVault; override with --build-arg.
|
||||||
|
# PB_ARCH is "amd64" (default) or "arm64" (e.g. Apple Silicon).
|
||||||
|
ARG PB_VERSION=0.22.21
|
||||||
|
ARG PB_ARCH=amd64
|
||||||
|
|
||||||
|
RUN apk add --no-cache ca-certificates tzdata unzip wget
|
||||||
|
|
||||||
|
WORKDIR /pb
|
||||||
|
RUN set -eux; \
|
||||||
|
wget -q -O /tmp/pb.zip \
|
||||||
|
"https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_${PB_ARCH}.zip"; \
|
||||||
|
unzip /tmp/pb.zip -d /pb; \
|
||||||
|
rm /tmp/pb.zip
|
||||||
|
|
||||||
|
# Schema + seed migrations (single source of truth in the API Server tree).
|
||||||
|
COPY ["API Server/pocketbase/pb_migrations/", "/pb/pb_migrations/"]
|
||||||
|
|
||||||
|
COPY ["Docker/pocketbase/entrypoint.sh", "/entrypoint.sh"]
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
# pb_data holds the SQLite database and uploads — mount a volume here.
|
||||||
|
VOLUME ["/pb/pb_data"]
|
||||||
|
EXPOSE 8070
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Create/update the superuser from env vars so the API Server can authenticate on
|
||||||
|
# first boot. `superuser upsert` is idempotent (PocketBase v0.22+/v0.23). Accepts
|
||||||
|
# either the PilotVault names (POCKETBASE_ADMIN_*) or the short PB_ADMIN_* aliases.
|
||||||
|
ADMIN_EMAIL="${POCKETBASE_ADMIN_EMAIL:-$PB_ADMIN_EMAIL}"
|
||||||
|
ADMIN_PASSWORD="${POCKETBASE_ADMIN_PASSWORD:-$PB_ADMIN_PASSWORD}"
|
||||||
|
|
||||||
|
if [ -n "$ADMIN_EMAIL" ] && [ -n "$ADMIN_PASSWORD" ]; then
|
||||||
|
echo "Ensuring PocketBase superuser $ADMIN_EMAIL exists..."
|
||||||
|
/pb/pocketbase superuser upsert "$ADMIN_EMAIL" "$ADMIN_PASSWORD" \
|
||||||
|
|| echo "warning: superuser upsert failed; create an admin via the UI at /_/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Serve. --migrationsDir applies the bundled JS migrations on boot, which
|
||||||
|
# create/reconcile every collection and seed the baseline org + accounts
|
||||||
|
# (including superadmin@pilotvault.local) — all idempotent.
|
||||||
|
exec /pb/pocketbase serve --http=0.0.0.0:8070 --migrationsDir=/pb/pb_migrations
|
||||||
@@ -36,7 +36,7 @@ in memory by the API Server and fanned out over WebSockets.
|
|||||||
| [`Fly App/`](Fly%20App/) | Flutter (Android) + Kotlin DJI MSDK V4 bridge | — | ✅ Built & run on a real device; live telemetry uplink |
|
| [`Fly App/`](Fly%20App/) | Flutter (Android) + Kotlin DJI MSDK V4 bridge | — | ✅ Built & run on a real device; live telemetry uplink |
|
||||||
| [`Adobe Plugin/`](Adobe%20Plugin/) | — | — | 🚧 Placeholder |
|
| [`Adobe Plugin/`](Adobe%20Plugin/) | — | — | 🚧 Placeholder |
|
||||||
| [`Phone App/`](Phone%20App/) | — | — | 🚧 Placeholder |
|
| [`Phone App/`](Phone%20App/) | — | — | 🚧 Placeholder |
|
||||||
| [`Docker/`](Docker/) · [`Docker AIO/`](Docker%20AIO/) | Docker Compose | `:8080` `:8090` `:8026` | ✅ Combined stack + single all-in-one container |
|
| [`Docker/`](Docker/) · [`Docker AIO/`](Docker%20AIO/) | Docker Compose | `:8080` `:8090` `:8070` | ✅ Combined stack + single all-in-one container |
|
||||||
|
|
||||||
## Data model (PocketBase)
|
## Data model (PocketBase)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user