Collapse the separate backend (Node) and frontend (nginx) images into one image where the Express backend serves the built React app in addition to the API and game content, so deployment is a single container and one origin. - Add a root Dockerfile with frontend-builder + backend-builder stages producing one runtime image; remove backend/ and frontend/ Dockerfiles, the nginx config, and the frontend entrypoint - Serve the frontend dist and SPA fallback from Express (config.serveFrontend / FRONTEND_DIST_PATH), before auth/maintenance so the shell always loads and before the API 404 so client routes resolve to index.html - Port the SPA-oriented CSP from nginx into Helmet, gated on serveFrontend; keep the strict API-only policy otherwise - Reduce both compose files to a single flashpoint-web service on WEB_PORT -> 3100; drop API_PORT, BACKEND_HOST, BACKEND_PORT - Build one image in the release workflow instead of a two-service matrix - Update .env.example, README, workflow README, and env var docs Also add .gitattributes (*.sh eol=lf) and normalize the entrypoint line endings — without it, Windows checkouts bake CRLF into the image and the shebang fails with "no such file or directory".
86 lines
3.0 KiB
YAML
86 lines
3.0 KiB
YAML
# =============================================================================
|
|
# Flashpoint Web - Production Docker Compose
|
|
# =============================================================================
|
|
# Single image serving both the API and the web UI.
|
|
# Uses a pre-built image from the container registry.
|
|
#
|
|
# Usage:
|
|
# 1. Copy .env.example to .env and configure required variables
|
|
# 2. docker compose up -d
|
|
#
|
|
# For local development with image building, use:
|
|
# docker compose -f docker-compose.dev.yml up -d --build
|
|
#
|
|
# User permissions:
|
|
# Set PUID/PGID to match your host user (run 'id -u' and 'id -g' to find)
|
|
# This ensures bind-mounted volumes have correct ownership
|
|
# =============================================================================
|
|
|
|
services:
|
|
flashpoint-web:
|
|
image: darkraise/flashpoint-web:${IMAGE_TAG:-latest}
|
|
container_name: flashpoint-web
|
|
restart: unless-stopped
|
|
ports:
|
|
# Serves both the UI and the API (/api, /game-proxy, /game-zip) on one port
|
|
- "${WEB_PORT:-80}:3100"
|
|
volumes:
|
|
- ${FLASHPOINT_HOST_PATH:?FLASHPOINT_HOST_PATH is required}:/data/flashpoint:ro
|
|
- ${DATA_PATH:-./data}:/app/data
|
|
- ${LOGS_PATH:-./logs}:/app/logs
|
|
environment:
|
|
- PUID=${PUID:-1000}
|
|
- PGID=${PGID:-1000}
|
|
- NODE_ENV=production
|
|
- SERVE_FRONTEND=true
|
|
- TZ=${TZ:-UTC}
|
|
- DOMAIN=${DOMAIN:-http://localhost:${WEB_PORT:-80}}
|
|
- LOG_LEVEL=${LOG_LEVEL:-info}
|
|
- JWT_SECRET=${JWT_SECRET:?JWT_SECRET is required}
|
|
- ENABLE_LOCAL_DB_COPY=${ENABLE_LOCAL_DB_COPY:-false}
|
|
- SQLITE_CACHE_SIZE=${SQLITE_CACHE_SIZE:--64000}
|
|
- SQLITE_MMAP_SIZE=${SQLITE_MMAP_SIZE:-268435456}
|
|
- ENABLE_CACHE_PREWARM=${ENABLE_CACHE_PREWARM:-true}
|
|
# Auth & rate limiting
|
|
- JWT_EXPIRES_IN=${JWT_EXPIRES_IN:-1h}
|
|
- BCRYPT_SALT_ROUNDS=${BCRYPT_SALT_ROUNDS:-10}
|
|
- RATE_LIMIT_WINDOW_MS=${RATE_LIMIT_WINDOW_MS:-60000}
|
|
- RATE_LIMIT_MAX_REQUESTS=${RATE_LIMIT_MAX_REQUESTS:-100}
|
|
# Application
|
|
- HOME_RECENT_HOURS=${HOME_RECENT_HOURS:-24}
|
|
- ENABLE_CGI=${ENABLE_CGI:-false}
|
|
# OpenTelemetry
|
|
- OTEL_ENABLED=${OTEL_ENABLED:-false}
|
|
- OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-}
|
|
- OTEL_API_KEY=${OTEL_API_KEY:-}
|
|
- OTEL_SERVICE_NAME=${OTEL_SERVICE_NAME:-flashpoint-web}
|
|
- OTEL_TRACES_ENABLED=${OTEL_TRACES_ENABLED:-true}
|
|
- OTEL_METRICS_ENABLED=${OTEL_METRICS_ENABLED:-true}
|
|
- OTEL_METRICS_EXPORT_INTERVAL=${OTEL_METRICS_EXPORT_INTERVAL:-60000}
|
|
- OTEL_LOG_LEVEL=${OTEL_LOG_LEVEL:-info}
|
|
healthcheck:
|
|
test: ["CMD", "curl", "--fail", "http://localhost:3100/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: "2.0"
|
|
memory: 2G
|
|
reservations:
|
|
cpus: "0.5"
|
|
memory: 512M
|
|
networks:
|
|
- flashpoint-network
|
|
|
|
networks:
|
|
flashpoint-network:
|
|
driver: bridge
|