# Production-Stack für Cards auf dem Mac Mini. # # Lebt unter ~/projects/cards/ auf mana-server (Forgejo-Klon von # git.mana.how/till/cards). Build-Contexte zeigen relativ in den # Repo, kein externes Image-Registry — Cards ist Greenfield-eigenständig # (Strategie B), kein Plattform-Coupling. # # Ports auf dem Mac Mini: # cards-postgres: 5436 (Plattform 5432, Dev 5435 sind belegt) # cards-minio S3: 9210 (cadvisor hat 9110 belegt) # cards-minio UI: 9211 # cards-api: 3191 (alt war 3072 → cards-api.mana.how) # cards-web: 5181 (alt war 5180 → cards.mana.how) # # Cutover (2026-05-08): cardecky.mana.how + cardecky-api.mana.how # zeigen via Cloudflare-Tunnel auf diese Container. Alte Hostnames # cards.mana.how / cards-api.mana.how → nginx :4400 → 301 zu # cardecky.* (User-Bookmark-Erhalt). # # Start (von ~/projects/cards/ auf mana-server): # docker compose -f infrastructure/docker-compose.production.yml \ # --env-file infrastructure/.env.production up -d --build # # Stop: # docker compose -f infrastructure/docker-compose.production.yml down services: cards-postgres: image: postgres:16-alpine container_name: cards-postgres restart: unless-stopped environment: POSTGRES_USER: cards POSTGRES_PASSWORD: ${CARDS_DB_PASSWORD:?missing CARDS_DB_PASSWORD} POSTGRES_DB: cards ports: - '127.0.0.1:5436:5432' volumes: - /Volumes/ManaData/cards/postgres:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U cards -d cards'] interval: 5s timeout: 3s retries: 20 cards-minio: image: minio/minio:latest container_name: cards-minio restart: unless-stopped command: server /data --console-address ':9001' environment: MINIO_ROOT_USER: cardsadmin MINIO_ROOT_PASSWORD: ${CARDS_S3_SECRET_KEY:?missing CARDS_S3_SECRET_KEY} ports: - '127.0.0.1:9210:9000' - '127.0.0.1:9211:9001' volumes: - /Volumes/ManaData/cards/minio:/data healthcheck: test: ['CMD', 'mc', 'ready', 'local'] interval: 5s timeout: 3s retries: 10 cards-api: image: cards-api:local container_name: cards-api build: context: ../ dockerfile: apps/api/Dockerfile args: NPM_AUTH_TOKEN: ${NPM_AUTH_TOKEN:?missing NPM_AUTH_TOKEN} restart: unless-stopped depends_on: cards-postgres: condition: service_healthy cards-minio: condition: service_healthy environment: DATABASE_URL: 'postgresql://cards:${CARDS_DB_PASSWORD}@cards-postgres:5432/cards' CARDS_API_PORT: 3081 CARDS_API_VERSION: ${CARDS_API_VERSION:-1.0.0} CARDS_PUBLIC_URL: https://cardecky.mana.how CARDS_DSGVO_SERVICE_KEY: ${CARDS_DSGVO_SERVICE_KEY:?missing CARDS_DSGVO_SERVICE_KEY} CARDS_S3_ENDPOINT: cards-minio CARDS_S3_PORT: 9000 CARDS_S3_USE_SSL: 'false' CARDS_S3_ACCESS_KEY: cardsadmin CARDS_S3_SECRET_KEY: ${CARDS_S3_SECRET_KEY} CARDS_S3_BUCKET: cards-media MANA_AUTH_URL: https://auth.mana.how MANA_CREDITS_URL: https://credits.mana.how CARDS_MANA_SERVICE_KEY: ${CARDS_MANA_SERVICE_KEY:-} CARDS_AUTH_DEV_STUB: ${CARDS_AUTH_DEV_STUB:-true} ports: - '127.0.0.1:3191:3081' cards-web: image: cards-web:local container_name: cards-web build: context: ../ dockerfile: apps/web/Dockerfile args: NPM_AUTH_TOKEN: ${NPM_AUTH_TOKEN:?missing NPM_AUTH_TOKEN} restart: unless-stopped depends_on: - cards-api environment: # SvelteKit `$env/dynamic/public` liest zur Runtime — daher # hier statt als Build-Arg. Wert landet im SSR-Init-Snapshot # und in client-fetches. PUBLIC_CARDS_API_URL: https://cardecky-api.mana.how PUBLIC_MANA_AUTH_URL: https://auth.mana.how CARDS_API_URL: https://cardecky-api.mana.how NODE_ENV: production ports: - '127.0.0.1:5181:3000'