Files
stiftung-management-system/compose.yml
SysAdmin Agent fd626a9c66
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy (push) Has been cancelled
Code Quality / quality (push) Has been cancelled
Fix GrampsWeb: remove broken STATIC_PATH/STATIC_URL config (STI-90)
GRAMPSWEB_STATIC_PATH was set to /ahnenforschung/static (a URL path)
instead of a filesystem path, causing GrampsWeb to return 404 on all
routes. Removed STATIC_PATH and STATIC_URL (defaults work correctly)
and simplified BASE_URL to /.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 21:02:01 +00:00

215 lines
6.6 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Production Docker Compose Configuration
# This file is used for production deployment via GitHub Actions
# For local development, use: docker-compose -f compose.dev.yml up
#
# IMPORTANT: This configuration requires ALL environment variables to be
# provided via the production server's .env file. No fallback values are
# included for security reasons.
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- dbdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
web:
build:
context: ./app
args:
APP_VERSION: ${APP_VERSION:-unknown}
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- DJANGO_ALLOWED_HOSTS=${DJANGO_ALLOWED_HOSTS}
- LANGUAGE_CODE=${LANGUAGE_CODE}
- TIME_ZONE=${TIME_ZONE}
- REDIS_URL=${REDIS_URL}
- SESSION_COOKIE_NAME=${SESSION_COOKIE_NAME}
- CSRF_COOKIE_NAME=${CSRF_COOKIE_NAME}
- GRAMPS_URL=${GRAMPS_URL}
- GRAMPS_USERNAME=${GRAMPS_USERNAME}
- GRAMPS_PASSWORD=${GRAMPS_PASSWORD}
- GRAMPS_API_TOKEN=${GRAMPS_API_TOKEN}
- IMAP_HOST=${IMAP_HOST}
- IMAP_PORT=${IMAP_PORT}
- IMAP_USER=${IMAP_USER}
- IMAP_PASSWORD=${IMAP_PASSWORD}
- IMAP_FOLDER=${IMAP_FOLDER}
- IMAP_USE_SSL=${IMAP_USE_SSL}
ports:
- "8081:8000"
volumes:
- ./app:/app
command: ["gunicorn", "core.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3"]
worker:
build:
context: ./app
args:
APP_VERSION: ${APP_VERSION:-unknown}
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- REDIS_URL=${REDIS_URL}
- GRAMPS_URL=${GRAMPS_URL}
- GRAMPS_USERNAME=${GRAMPS_USERNAME}
- GRAMPS_PASSWORD=${GRAMPS_PASSWORD}
- GRAMPS_API_TOKEN=${GRAMPS_API_TOKEN}
- IMAP_HOST=${IMAP_HOST}
- IMAP_PORT=${IMAP_PORT}
- IMAP_USER=${IMAP_USER}
- IMAP_PASSWORD=${IMAP_PASSWORD}
- IMAP_FOLDER=${IMAP_FOLDER}
- IMAP_USE_SSL=${IMAP_USE_SSL}
depends_on:
- redis
- db
command: ["celery", "-A", "core", "worker", "-l", "info"]
beat:
build:
context: ./app
args:
APP_VERSION: ${APP_VERSION:-unknown}
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
- DJANGO_DEBUG=${DJANGO_DEBUG}
- REDIS_URL=${REDIS_URL}
- GRAMPS_URL=${GRAMPS_URL}
- GRAMPS_USERNAME=${GRAMPS_USERNAME}
- GRAMPS_PASSWORD=${GRAMPS_PASSWORD}
- GRAMPS_API_TOKEN=${GRAMPS_API_TOKEN}
- IMAP_HOST=${IMAP_HOST}
- IMAP_PORT=${IMAP_PORT}
- IMAP_USER=${IMAP_USER}
- IMAP_PASSWORD=${IMAP_PASSWORD}
- IMAP_FOLDER=${IMAP_FOLDER}
- IMAP_USE_SSL=${IMAP_USE_SSL}
depends_on:
- redis
- db
command: ["celery", "-A", "core", "beat", "-l", "info"]
mcp:
build:
context: ./app
args:
APP_VERSION: ${APP_VERSION:-unknown}
depends_on:
db:
condition: service_healthy
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
- DJANGO_DEBUG=0
- DJANGO_ALLOWED_HOSTS=localhost
- LANGUAGE_CODE=${LANGUAGE_CODE}
- TIME_ZONE=${TIME_ZONE}
- MCP_TOKEN_READONLY=${MCP_TOKEN_READONLY}
- MCP_TOKEN_EDITOR=${MCP_TOKEN_EDITOR}
- MCP_TOKEN_ADMIN=${MCP_TOKEN_ADMIN}
# Kein Port-Mapping nur internes Netz
# Start via: docker compose run --rm -e MCP_AUTH_TOKEN=<token> mcp
stdin_open: true
command: ["python", "-m", "mcp_server"]
ollama:
image: ollama/ollama:latest
# Kein externes Port-Mapping — nur über internes Docker-Netzwerk erreichbar
# Django-App: http://ollama:11434
environment:
- OLLAMA_MAX_LOADED_MODELS=1
- OLLAMA_NUM_PARALLEL=1
- OLLAMA_DEFAULT_MODEL=${OLLAMA_DEFAULT_MODEL:-qwen2.5:3b}
volumes:
- ollama_data:/root/.ollama
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:11434/api/tags || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
# Beim ersten Start: Ollama starten, dann Modell laden (falls nicht vorhanden)
entrypoint: >
sh -c "
ollama serve &
OLLAMA_PID=$$!
echo '[ollama] Warte auf API...'
RETRIES=0
until curl -sf http://localhost:11434/api/tags > /dev/null 2>&1; do
RETRIES=$$((RETRIES + 1))
[ $$RETRIES -ge 60 ] && echo '[ollama] FEHLER: API nicht bereit.' && exit 1
sleep 1
done
MODEL=$${OLLAMA_DEFAULT_MODEL:-qwen2.5:3b}
if ollama list | grep -q \"$$MODEL\"; then
echo \"[ollama] Modell '$$MODEL' bereits vorhanden.\"
else
echo \"[ollama] Lade Modell '$$MODEL'...\"
ollama pull \"$$MODEL\"
fi
wait $$OLLAMA_PID
"
grampsweb:
image: ghcr.io/gramps-project/grampsweb:latest
ports:
- "8090:5000"
environment:
- GRAMPSWEB_SECRET_KEY=${GRAMPSWEB_SECRET_KEY}
- GRAMPSWEB_ADMIN_EMAIL=${GRAMPSWEB_ADMIN_EMAIL}
- GRAMPSWEB_ADMIN_PASSWORD=${GRAMPSWEB_ADMIN_PASSWORD}
- GRAMPSWEB_TREE=${GRAMPSWEB_TREE:-Stiftung}
- GRAMPSWEB_BASE_URL=${GRAMPSWEB_BASE_URL:-/}
- GRAMPSWEB_CELERY_CONFIG__broker_url=redis://redis:6379/0
- GRAMPSWEB_CELERY_CONFIG__result_backend=redis://redis:6379/0
- GRAMPSWEB_RATELIMIT_STORAGE_URI=redis://redis:6379/1
- GRAMPSWEB_NEW_DB_BACKEND=sqlite
volumes:
- gramps_data:/app/data
depends_on:
- db
- redis
volumes:
dbdata:
gramps_data:
ollama_data: