Files
tessera-ctl/docker-compose.prod.yml
T
schalli dab72eb1f9 fix(compose): user-files dauerhaft speichern und Betriebshandbuch nachziehen
- docker-compose.yml und docker-compose.prod.yml mounten /app/user-files
  im Dienst api auf ein neues benanntes Volume user-files (Eigentuemerschaft
  uid 1001 folgt aus dem Image, kein Bind-Mount)
- docker-compose.dev.yml bleibt unveraendert (Compose fuehrt Mount-Listen
  ueber das Ziel zusammen)
- Betriebshandbuch Kapitel 6: Speicher als dauerhaft beschrieben, Mount-Zeile
  woertlich zum Kopieren, Hinweis dass /opt/tessera/docker-compose.yml auf
  dem Server separat gepflegt werden muss (Deploy erreicht sie nicht)
- Betriebshandbuch Kapitel 7: Fehlerzeile zu verschwundenen Avataren/Exporten
  an den reparierten Repository-Stand angepasst

WINDOWS #17 bleibt offen, bis die Serverdatei manuell ergaenzt ist.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYZcd3SSmo14QTqWx2KKzU
2026-09-09 09:34:15 +02:00

94 lines
2.9 KiB
YAML

services:
web:
image: git.vicolab.de/schalli/tessera-ctl/web:latest
restart: unless-stopped
ports:
- "3000:3000"
environment:
HOSTNAME: "0.0.0.0"
# Read by the browser, not by the web container, so it must be an address
# that resolves outside Docker. http://api:3001 only exists on the compose
# network and leaves the UI unable to reach the API.
NEXT_PUBLIC_API_URL: ${APP_URL:-http://localhost:3001}
API_INTERNAL_URL: "http://api:3001"
JWT_SECRET: ${JWT_SECRET}
networks:
- frontend-net
- backend-net
depends_on:
api:
condition: service_healthy
api:
image: git.vicolab.de/schalli/tessera-ctl/api:latest
restart: unless-stopped
ports:
- "3001:3001"
networks:
- backend-net
- data-net
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: ${DATABASE_URL}
JWT_SECRET: ${JWT_SECRET}
TESSERA_ADMIN_USER: ${TESSERA_ADMIN_USER:-admin}
TESSERA_ADMIN_EMAIL: ${TESSERA_ADMIN_EMAIL}
TESSERA_ADMIN_PASSWORD: ${TESSERA_ADMIN_PASSWORD}
TESSERA_FORCE_CHANGE: ${TESSERA_FORCE_CHANGE:-true}
TESSERA_SMTP_HOST: ${TESSERA_SMTP_HOST:-}
TESSERA_SMTP_PORT: ${TESSERA_SMTP_PORT:-587}
TESSERA_SMTP_SECURE: ${TESSERA_SMTP_SECURE:-false}
TESSERA_SMTP_USER: ${TESSERA_SMTP_USER:-}
TESSERA_SMTP_PASSWORD: ${TESSERA_SMTP_PASSWORD:-}
TESSERA_SMTP_FROM: ${TESSERA_SMTP_FROM:-Tessera <noreply@tessera.local>}
TESSERA_APP_URL: ${APP_URL:-http://localhost:3000}
# Unset used to resolve to an empty value and only fail later, inside the
# API, with a stack trace. Fail at compose level with a usable message
# instead. Generate with: openssl rand -hex 32
#
# CALENDAR_ENCRYPTION_KEY is the previous name and is still accepted, so
# an existing .env keeps working; the API logs a deprecation warning when
# it falls back to it.
TESSERA_ENCRYPTION_KEY: "${TESSERA_ENCRYPTION_KEY:-${CALENDAR_ENCRYPTION_KEY:?set TESSERA_ENCRYPTION_KEY in .env, generate one with openssl rand -hex 32}}"
CALENDAR_ENCRYPTION_KEY: "${CALENDAR_ENCRYPTION_KEY:-}"
volumes:
- user-files:/app/user-files
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3001/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 20s
db:
image: postgres:16-alpine
restart: unless-stopped
networks:
- data-net
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_USER: tessera
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: tessera
healthcheck:
test: ["CMD-SHELL", "pg_isready -U tessera"]
interval: 5s
timeout: 3s
retries: 5
networks:
frontend-net:
driver: bridge
backend-net:
driver: bridge
data-net:
driver: bridge
internal: true
volumes:
pgdata:
user-files: