Minimal API slice /api/tasks (idempotent create with client ids, versioned updates, state-based status changes, checklist, parent approval/rejection, points overview and audited adjustments, recurring next instance), per-user SignalR broadcasts that respect private tasks, /api/push subscription endpoints, a dependency-free Web Push sender (RFC 8291/8292) and a minimal reminder service. VAPID keys via Aspire parameters and deploy/.env (tools/generate-vapid-keys.cs); integration test login limit raised. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
129 lines
3.7 KiB
YAML
129 lines
3.7 KiB
YAML
# Produktivbetrieb auf einem Linux-Docker-Host.
|
||
#
|
||
# cp .env.example .env # Werte anpassen!
|
||
# docker compose up -d --build
|
||
# docker compose --profile proxy up -d --build # inkl. Caddy (HTTPS mit Let's Encrypt)
|
||
#
|
||
# Die Anwendung verlangt HTTPS (Secure-Cookies). Ohne Caddy entweder einen eigenen Reverse Proxy
|
||
# mit TLS davor setzen oder nur über http://localhost testen.
|
||
|
||
name: familyplanner
|
||
|
||
x-app-build: &app-build
|
||
context: ..
|
||
dockerfile: Dockerfile
|
||
|
||
x-connection-string: &connection-string
|
||
ConnectionStrings__familyplannerdb: "Server=sql,1433;Database=familyplannerdb;User Id=sa;Password=${SQL_SA_PASSWORD};TrustServerCertificate=True;Encrypt=True"
|
||
|
||
services:
|
||
sql:
|
||
image: mcr.microsoft.com/mssql/server:2022-latest
|
||
# Das Image läuft als Benutzer "mssql" (non-root).
|
||
environment:
|
||
ACCEPT_EULA: "Y"
|
||
MSSQL_SA_PASSWORD: ${SQL_SA_PASSWORD:?SQL_SA_PASSWORD in .env setzen}
|
||
MSSQL_PID: ${MSSQL_PID:-Express}
|
||
TZ: Europe/Berlin
|
||
volumes:
|
||
- sql-data:/var/opt/mssql
|
||
- sql-backup:/var/opt/mssql/backup
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P \"$$MSSQL_SA_PASSWORD\" -C -b -Q 'SELECT 1' > /dev/null"]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 20
|
||
start_period: 30s
|
||
restart: unless-stopped
|
||
|
||
migrations:
|
||
image: ${REGISTRY:-}familyplanner-migrations:${TAG:-latest}
|
||
build:
|
||
<<: *app-build
|
||
args:
|
||
PROJECT: FamilyPlanner.MigrationService
|
||
environment:
|
||
<<: *connection-string
|
||
DOTNET_ENVIRONMENT: Production
|
||
Seed__AdminUserName: ${ADMIN_USERNAME:-admin}
|
||
Seed__AdminPassword: ${ADMIN_PASSWORD:?ADMIN_PASSWORD in .env setzen}
|
||
Seed__AdminEmail: ${ADMIN_EMAIL:-}
|
||
Seed__FamilyName: ${FAMILY_NAME:-}
|
||
depends_on:
|
||
sql:
|
||
condition: service_healthy
|
||
restart: "no"
|
||
|
||
api:
|
||
image: ${REGISTRY:-}familyplanner-api:${TAG:-latest}
|
||
build:
|
||
<<: *app-build
|
||
args:
|
||
PROJECT: FamilyPlanner.Api
|
||
environment:
|
||
<<: *connection-string
|
||
ASPNETCORE_ENVIRONMENT: Production
|
||
TZ: Europe/Berlin
|
||
# Web-Push-Erinnerungen (optional, ADR-0014) – leer = deaktiviert
|
||
WebPush__PublicKey: ${VAPID_PUBLIC_KEY:-}
|
||
WebPush__PrivateKey: ${VAPID_PRIVATE_KEY:-}
|
||
WebPush__Subject: ${VAPID_SUBJECT:-mailto:admin@localhost}
|
||
depends_on:
|
||
migrations:
|
||
condition: service_completed_successfully
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
|
||
interval: 15s
|
||
timeout: 5s
|
||
retries: 5
|
||
start_period: 20s
|
||
restart: unless-stopped
|
||
|
||
web:
|
||
image: ${REGISTRY:-}familyplanner-web:${TAG:-latest}
|
||
build:
|
||
<<: *app-build
|
||
args:
|
||
PROJECT: FamilyPlanner.Web
|
||
environment:
|
||
ASPNETCORE_ENVIRONMENT: Production
|
||
TZ: Europe/Berlin
|
||
# Service Discovery: Adresse der Api im Docker-Netz (YARP-BFF)
|
||
services__api__http__0: http://api:8080
|
||
ports:
|
||
- "${WEB_BIND:-127.0.0.1}:${WEB_PORT:-8080}:8080"
|
||
depends_on:
|
||
api:
|
||
condition: service_healthy
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-fsS", "http://localhost:8080/alive"]
|
||
interval: 15s
|
||
timeout: 5s
|
||
retries: 5
|
||
start_period: 15s
|
||
restart: unless-stopped
|
||
|
||
caddy:
|
||
profiles: ["proxy"]
|
||
image: caddy:2
|
||
environment:
|
||
DOMAIN: ${DOMAIN:-localhost}
|
||
ports:
|
||
- "80:80"
|
||
- "443:443"
|
||
- "443:443/udp"
|
||
volumes:
|
||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||
- caddy-data:/data
|
||
- caddy-config:/config
|
||
depends_on:
|
||
web:
|
||
condition: service_healthy
|
||
restart: unless-stopped
|
||
|
||
volumes:
|
||
sql-data:
|
||
sql-backup:
|
||
caddy-data:
|
||
caddy-config:
|