# LudosData — full stack. # # cp .env.example .env # then edit the secrets # docker compose up --build # # The SPA is served by nginx on http://localhost:8080, which also reverse-proxies # /api and /uploads to the API container. Because everything is same-origin in # this setup, the browser never issues a cross-origin request and CORS is not in # play at all — the API's CORS policy only matters for `ng serve` on :4200. services: api: build: context: ./backend image: ludosdata-api restart: unless-stopped environment: ASPNETCORE_ENVIRONMENT: Production # Required. Startup fails loudly if this is missing or under 32 chars. Jwt__Key: ${JWT_KEY:?JWT_KEY is required — see .env.example} Jwt__Issuer: ${JWT_ISSUER:-LudosData} Jwt__Audience: ${JWT_AUDIENCE:-LudosData} Jwt__LifetimeMinutes: ${JWT_LIFETIME_MINUTES:-720} # Creates the first account and imports the 105 games from the 2018 dump, # but only while the database has no users at all. Seed__Enabled: ${SEED_ENABLED:-true} Seed__UserName: ${SEED_USERNAME:-} Seed__Email: ${SEED_EMAIL:-} Seed__Password: ${SEED_PASSWORD:-} # Only consulted when the SPA is served from somewhere other than nginx. Cors__AllowedOrigins__0: ${CORS_ORIGIN:-http://localhost:8080} Cors__AllowedOrigins__1: http://localhost:4200 volumes: # SQLite file and uploaded box art. This is the only stateful thing in the # stack — back this volume up and you have backed up everything. - ludos-data:/data expose: - "8080" healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8080/health || exit 1"] interval: 15s timeout: 3s retries: 5 start_period: 20s web: build: context: ./frontend image: ludosdata-web restart: unless-stopped depends_on: api: condition: service_healthy ports: - "${WEB_PORT:-8080}:8080" healthcheck: # 127.0.0.1, not localhost: nginx listens on IPv4 only, and BusyBox wget # resolves localhost to ::1 first and gets connection-refused. test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1:8080/ || exit 1"] interval: 15s timeout: 3s retries: 5 start_period: 10s volumes: ludos-data: