Files
tajniak81andClaude Opus 4.8 2d20f6f29c 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>
2026-07-19 19:16:21 +02:00

151 lines
5.7 KiB
Docker

# syntax=docker/dockerfile:1
#
# All-in-one PilotVault image: PocketBase + API Server + Web App in ONE container,
# supervised by supervisord. Convenience/demo image — for production run the three
# services separately (see Docker/docker-compose.yml).
#
# BUILD CONTEXT MUST BE THE REPO ROOT (this Dockerfile COPYs from "API Server/"
# and "Web App/"). From E:\VS Code Projects\PilotVault run:
#
# docker build -f "Docker AIO/Dockerfile" -t pilotvault-aio .
# docker run -p 8090:8090 -p 8080:8080 -p 8070:8070 \
# -v pilotvault_pb:/pb/pb_data pilotvault-aio
#
# 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)
# =============================================================================
FROM node:22-alpine AS panel
WORKDIR /panel
COPY ["API Server/panel/package.json", "API Server/panel/package-lock.json", "./"]
RUN npm ci
COPY ["API Server/panel/", "./"]
RUN npm run build
# =============================================================================
# Stage 2 — build the API Server static binary (go.mod pins go 1.26)
# =============================================================================
FROM golang:1.26-alpine AS api-build
WORKDIR /src
COPY ["API Server/go.mod", "API Server/go.sum", "./"]
RUN go mod download
COPY ["API Server/cmd/", "./cmd/"]
COPY ["API Server/internal/", "./internal/"]
# Overlay the freshly built panel so //go:embed all:dist picks it up.
COPY --from=panel /internal/api/dist ./internal/api/dist
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" \
-o /out/api-server ./cmd/server
# =============================================================================
# Stage 3 — build the Web App's embedded Vue UI (-> web/)
# =============================================================================
FROM node:22-alpine AS ui
WORKDIR /ui
COPY ["Web App/ui/package.json", "Web App/ui/package-lock.json", "./"]
RUN npm ci
COPY ["Web App/ui/", "./"]
RUN npm run build
# =============================================================================
# Stage 4 — build the Web App static binary (go.mod pins go 1.24)
# =============================================================================
FROM golang:1.24-alpine AS web-build
WORKDIR /src
COPY ["Web App/go.mod", "Web App/go.sum", "./"]
RUN go mod download
COPY ["Web App/main.go", "Web App/bff.go", "./"]
# Overlay the freshly built UI so //go:embed web picks it up.
COPY --from=ui /web ./web
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" \
-o /out/dji-web-app .
# =============================================================================
# Stage 5 — fetch the PocketBase binary
# =============================================================================
FROM alpine:latest AS pocketbase
# Override with --build-arg PB_VERSION=x.y.z / PB_ARCH=arm64 as needed.
ARG PB_VERSION=0.22.21
ARG PB_ARCH=amd64
RUN apk add --no-cache unzip wget ca-certificates \
&& wget -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
# =============================================================================
# Stage 6 — runtime: alpine:latest running all three under supervisord
# =============================================================================
FROM alpine:latest
RUN apk add --no-cache ca-certificates tzdata supervisor
WORKDIR /app
COPY --from=api-build /out/api-server ./api-server
COPY --from=web-build /out/dji-web-app ./dji-web-app
COPY --from=pocketbase /pb/pocketbase ./pocketbase
# JS migrations (schema + seed accounts) applied by PocketBase on first serve.
COPY ["API Server/pocketbase/pb_migrations/", "/pb/pb_migrations/"]
# --- Runtime configuration (loopback-wired between the three services) ---------
# API Server reads API_ADDR / POCKETBASE_URL / CORS_ALLOW_ORIGINS / POCKETBASE_ADMIN_*
# Web App reads ADDR / API_BASE
# NOTE: these bundle default credentials for convenience — override at `docker run`.
ENV API_ADDR=":8080" \
POCKETBASE_URL="http://127.0.0.1:8070" \
CORS_ALLOW_ORIGINS="*" \
POCKETBASE_ADMIN_EMAIL="admin@dji.local" \
POCKETBASE_ADMIN_PASSWORD="djiadmin2026!" \
ADDR=":8090" \
API_BASE="http://127.0.0.1:8080"
# --- supervisord: PocketBase first, then API Server, then Web App --------------
RUN cat > /etc/supervisord.conf <<'EOF'
[supervisord]
nodaemon=true
user=root
logfile=/dev/null
logfile_maxbytes=0
pidfile=/run/supervisord.pid
[program:pocketbase]
priority=10
directory=/pb
# 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:8070 --dir=/pb/pb_data --migrationsDir=/pb/pb_migrations"
autorestart=true
startsecs=3
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:api-server]
priority=20
directory=/app
command=/app/api-server
autorestart=true
startsecs=3
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:web-app]
priority=30
directory=/app
command=/app/dji-web-app
autorestart=true
startsecs=3
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
EOF
# PocketBase data (SQLite). Mount a volume here to persist across restarts.
VOLUME ["/pb/pb_data"]
EXPOSE 8090 8080 8070
ENTRYPOINT ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]