media-rip/docker-compose.example.yml
xpltd 5a6eb00906 Docker self-hosting: fix persistence, add data_dir config
Critical fix:
- Dockerfile env var was MEDIARIP__DATABASE__PATH (ignored) — now MEDIARIP__SERVER__DB_PATH
  DB was landing at /app/mediarip.db (lost on restart) instead of /data/mediarip.db

Persistence model:
- /downloads → media files (bind mount recommended)
- /data → SQLite DB, session cookies, error logs (named volume)
- /themes → custom CSS themes (read-only bind mount)
- /app/config.yaml → optional YAML config (read-only bind mount)

Other changes:
- Add server.data_dir config field (default: /data) for explicit session storage
- Cookie storage uses data_dir instead of fragile path math from output_dir parent
- Lifespan creates data_dir on startup
- .dockerignore excludes tests, dev DB, egg-info
- docker-compose.yml: inline admin/purge config examples
- docker-compose.example.yml: parameterized with env vars
- .env.example: session mode, clearer docs
- README: Docker volumes table, admin setup docs, full config reference
- PROJECT.md: reflects completed v1.0 state
- REQUIREMENTS.md: all 26 requirements validated
2026-03-19 09:56:10 -05:00

62 lines
1.9 KiB
YAML

# media.rip() — Docker Compose with Caddy reverse proxy (recommended for production)
#
# Caddy automatically provisions TLS certificates via Let's Encrypt.
#
# Setup:
# 1. Copy .env.example to .env and fill in your values
# 2. Run: docker compose -f docker-compose.example.yml up -d
#
# Generate a bcrypt password hash:
# docker run --rm python:3.12-slim python -c \
# "import bcrypt; print(bcrypt.hashpw(b'YOUR_PASSWORD', bcrypt.gensalt()).decode())"
services:
media-rip:
image: ghcr.io/xpltdco/media-rip:latest
container_name: media-rip
restart: unless-stopped
volumes:
- downloads:/downloads # Downloaded media files
- data:/data # Database, sessions, error logs
# Optional:
# - ./themes:/themes:ro # Custom theme CSS overrides
# - ./config.yaml:/app/config.yaml:ro # YAML config file
environment:
# Admin panel
MEDIARIP__ADMIN__ENABLED: "true"
MEDIARIP__ADMIN__USERNAME: "${ADMIN_USERNAME:-admin}"
MEDIARIP__ADMIN__PASSWORD_HASH: "${ADMIN_PASSWORD_HASH}"
# Session mode: isolated (default), shared, or open
MEDIARIP__SESSION__MODE: "${SESSION_MODE:-isolated}"
# Auto-purge (optional)
# MEDIARIP__PURGE__ENABLED: "true"
# MEDIARIP__PURGE__MAX_AGE_HOURS: "168"
expose:
- "8000"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health')"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
caddy:
image: caddy:2-alpine
container_name: media-rip-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
media-rip:
condition: service_healthy
volumes:
downloads:
data:
caddy_data:
caddy_config: