PocketBase as the data layer: client, compose stack, dev environment and tests #28

Merged
Tom merged 4 commits from feature/pocketbase-client into main 2026-09-23 11:09:31 +02:00
5 changed files with 109 additions and 15 deletions
Showing only changes of commit bbe792192d - Show all commits

No files matched your search

+1
View File
@@ -20,3 +20,4 @@ docs/
Dockerfile Dockerfile
.dockerignore .dockerignore
compose.yaml compose.yaml
compose.dev.yaml
+32
View File
@@ -0,0 +1,32 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="DevEnvironment" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
<deployment type="docker-compose.yml">
<settings>
<option name="envFilePath" value="" />
<option name="envFilePaths">
<list>
<option value="" />
</list>
</option>
<option name="commandLineOptions" value="--build" />
<!-- Base compose (loaded first); the dev overlay in sourceFilePath wins. -->
<option name="secondarySourceFiles">
<list>
<option value="$PROJECT_DIR$/compose.yaml" />
</list>
</option>
<option name="services">
<list>
<option value="eb-pocketbase" />
<option value="eb-web" />
</list>
</option>
<!-- Dev overlay (primary = last applied): host ports + local web build. -->
<option name="sourceFilePath" value="$PROJECT_DIR$/compose.dev.yaml" />
<option name="upForceRecreate" value="true" />
</settings>
</deployment>
<EXTENSION ID="com.jetbrains.rider.docker.debug" isFastModeEnabled="true" isSslEnabled="false" />
<method v="2" />
</configuration>
</component>
+8 -2
View File
@@ -4,9 +4,15 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src WORKDIR /src
# Copy only the csproj and restore first, so the NuGet restore layer stays # Copy the solution-wide build files first (Central Package Management lives in
# cached as long as the dependencies do not change. # Directory.Packages.props; without it a restore fails with NU1015). Then the
# csproj of every project in the web app's dependency tree. Restoring before
# copying the rest of the source keeps the NuGet layer cached as long as the
# dependencies do not change.
COPY Directory.Build.props Directory.Packages.props ./
COPY Elternbeirat.Web/Elternbeirat.Web.csproj Elternbeirat.Web/ COPY Elternbeirat.Web/Elternbeirat.Web.csproj Elternbeirat.Web/
COPY Elternbeirat.PocketBase/Elternbeirat.PocketBase.csproj Elternbeirat.PocketBase/
COPY Elternbeirat.Contracts/Elternbeirat.Contracts.csproj Elternbeirat.Contracts/
RUN dotnet restore Elternbeirat.Web/Elternbeirat.Web.csproj RUN dotnet restore Elternbeirat.Web/Elternbeirat.Web.csproj
# Then the rest of the source. # Then the rest of the source.
+38
View File
@@ -0,0 +1,38 @@
# Dev overlay: layered on top of compose.yaml for local development.
# docker compose -f compose.yaml -f compose.dev.yaml up --build
#
# It adds host port mappings (so the stack is reachable from the browser), builds
# the web image from local source instead of pulling it from the registry, and
# swaps the Unraid pb_data bind mount for a throwaway named volume (the /mnt/user
# path only exists on the server).
services:
eb-pocketbase:
ports:
- "8090:8090" # PocketBase admin UI at http://localhost:8090/_/
environment:
# Local only: on a fresh pb_data the image auto-creates this superuser, so
# you skip the /_/ setup screen. Same credentials as the test fixture. This
# stays out of the prod base -- there the superuser is set up by hand / #9.
PB_ADMIN_EMAIL: test@example.com
PB_ADMIN_PASSWORD: test-password
volumes:
# Local: a named Docker volume instead of the Unraid /mnt/user bind mount
# from the base file (that path only exists on the server). The "!reset"
# tag clears the inherited bind mount so only this volume applies.
- !reset null
- pb_data_dev:/pb_data
eb-web:
# Build from local source instead of pulling the registry image, so local code
# changes show up without a push+CI round-trip. image: "" clears the inherited
# tag from the base, which forces compose to use the build below.
image: ""
build:
context: .
dockerfile: Dockerfile
ports:
- "5000:8080" # web app at http://localhost:5000
volumes:
pb_data_dev: # throwaway local volume; remove with `docker volume rm`
+30 -13
View File
@@ -1,24 +1,41 @@
# TEST setup for the first run on Unraid (without NPM). # Base compose: production-like. Both services, no host port mappings (NPM is the
# only path to the web app; the editors reach PocketBase through an NPM subdomain).
# Only PocketBase's data is a volume; everything else lives inside the images.
# #
# Pulls the finished image from the Gitea registry (the build happens on the # For local development use the dev overlay on top, which adds host ports and builds
# development machine, see docs/deployment.md) instead of building from source # the web image from source:
# on Unraid. # docker compose -f compose.yaml -f compose.dev.yaml up --build
# (The Rider run config "DevEnvironment" does exactly this with one click.)
# #
# Deliberately differs from the production setup: # Startup order: PocketBase comes up first; once it reports healthy the web app
# - There is a port mapping (5000 outside -> 8080 inside) so the app is # starts (depends_on -> service_healthy).
# reachable in the local network at http://<unraid>:5000. In production the
# mapping is dropped; there NPM is the only path to the container (use the
# external npm network instead, see docs/deployment.md).
#
# Once NPM is in place, this file is replaced by the production compose.
services: services:
eb-pocketbase:
image: ghcr.io/muchobien/pocketbase:0.40.4
container_name: eb-pocketbase
restart: unless-stopped
environment:
TZ: Europe/Berlin
volumes:
# The only state that must survive a restart or redeploy.
- /mnt/user/appdata/pocketbase/pb_data:/pb_data
healthcheck:
# The image ships this endpoint; the web app waits for it to pass.
test: ["CMD", "wget", "--spider", "-q", "http://localhost:8090/api/health"]
interval: 5s
timeout: 3s
retries: 10
eb-web: eb-web:
image: gitea.anticarnist.de/tom/elternbeirat:latest image: gitea.anticarnist.de/tom/elternbeirat:latest
container_name: eb-web container_name: eb-web
restart: unless-stopped restart: unless-stopped
depends_on:
eb-pocketbase:
condition: service_healthy
environment: environment:
ASPNETCORE_URLS: http://+:8080 ASPNETCORE_URLS: http://+:8080
TZ: Europe/Berlin TZ: Europe/Berlin
ports: # The web app reads content from PocketBase over the compose network.
- "5000:8080" # TEST access, remove in production PocketBase__BaseUrl: http://eb-pocketbase:8090