lotr-sut/docker-compose.yml
Fellowship Scholar f6a5823439 init commit
2026-03-29 20:07:56 +00:00

119 lines
4.5 KiB
YAML

# version is obsolete in newer docker-compose versions
#
# Environment-aware Docker Compose configuration
# Supports both production (fellowship) and local dev (fellowship-local) stacks
# Usage:
# Production: cp .env.prod .env && docker-compose up -d (containers: fellowship_*)
# Local dev: cp .env.local .env && docker-compose up -d (containers: fellowship-local_*)
#
# The COMPOSE_PROJECT_NAME environment variable controls container naming:
# - Omitted or 'fellowship' → containers: fellowship_backend_1, fellowship_frontend_1
# - 'fellowship-local' → containers: fellowship-local_backend_1, fellowship-local_frontend_1
#
# This allows both environments to coexist without conflicts.
services:
backend:
build:
context: ./sut/backend
dockerfile: Dockerfile
# ✓ No container_name: allows COMPOSE_PROJECT_NAME-based naming
# Port 5000 is intentionally NOT exposed to the host — backend is only reached
# via Caddy reverse-proxy (internal Docker network: backend:5000).
# macOS AirPlay Receiver occupies host port 5000 (Monterey+), so binding it
# would fail. Direct API access for debugging: docker exec or /api through Caddy.
volumes:
- backend_data:/app/data
- ./sut/backend:/app
# Exclude node_modules and data from volume mount to avoid conflicts
environment:
- FLASK_APP=app.py
- FLASK_ENV=development
- DATABASE_URL=sqlite:////app/data/fellowship.db
- SECRET_KEY=dev-secret-key-change-in-production
- AZURE_OPENAI_ENDPOINT=${AZURE_OPENAI_ENDPOINT:-}
- AZURE_OPENAI_API_KEY=${AZURE_OPENAI_API_KEY:-}
- AZURE_OPENAI_DEPLOYMENT=${AZURE_OPENAI_DEPLOYMENT:-}
- AZURE_OPENAI_API_VERSION=${AZURE_OPENAI_API_VERSION:-}
working_dir: /app
command: python app.py
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
frontend:
build:
context: ./sut/frontend
dockerfile: Dockerfile
# ✓ No container_name: allows COMPOSE_PROJECT_NAME-based naming
# Port 3000 is intentionally NOT exposed to the host — Caddy reverse-proxies
# to frontend:3000 via the internal Docker network. Colima's sshfs SSH tunnels
# conflict with host-bound :3000, so we leave it unmapped.
volumes:
- ./sut/frontend:/app
- frontend_node_modules:/app/node_modules
environment:
- REACT_APP_API_URL=/api
- REACT_APP_ENABLE_TEST_CONTROLS=${REACT_APP_ENABLE_TEST_CONTROLS:-true}
- CHOKIDAR_USEPOLLING=true
- SKIP_PREFLIGHT_CHECK=true
- DISABLE_ESLINT_PLUGIN=true
- FAST_REFRESH=false
- FRONTEND_MODE=${FRONTEND_MODE:-dev}
- NODE_ENV=development
- WDS_SOCKET_PORT=${WDS_SOCKET_PORT:-80}
- WDS_SOCKET_HOST=${CADDY_DOMAIN:-localhost}
- WDS_SOCKET_PROTOCOL=${WDS_SOCKET_PROTOCOL:-ws}
- WDS_SOCKET_PATH=${WDS_SOCKET_PATH:-/ws}
command: sh -c "npm install && if [ \"${FRONTEND_MODE:-dev}\" = \"prod\" ]; then npm run build && npx --yes serve -s build -l 3000; else npm start; fi"
depends_on:
- backend
restart: unless-stopped
caddy:
image: caddy:2-alpine
# ✓ No container_name: allows COMPOSE_PROJECT_NAME-based naming
ports:
- "80:80"
- "443:443"
volumes:
- ${CADDYFILE_PATH:-./caddy/Caddyfile.local}:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
environment:
# Use CADDY_DOMAIN from environment/env file, fallback to localhost for local development
CADDY_DOMAIN: ${CADDY_DOMAIN:-localhost}
# DevOps Escape Room HTTPS subdomains — prepend jenkins-/ide- to CADDY_DOMAIN.
# These env vars are required when using Caddyfile (staging) or Caddyfile.prod.
# They are NOT needed when using Caddyfile.local (CI / local HTTP-only dev).
JENKINS_DOMAIN: ${JENKINS_DOMAIN:-}
IDE_DOMAIN: ${IDE_DOMAIN:-}
GITEA_DOMAIN: ${GITEA_DOMAIN:-}
# Allow Caddy to reach services in the devops-escape-room compose stack
# (Jenkins on host:8080 and code-server on host:8443) via host.docker.internal.
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
- backend
- frontend
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/"]
interval: 10s
timeout: 5s
retries: 3
start_period: 20s
volumes:
backend_data:
driver: local
frontend_node_modules:
driver: local
caddy_data:
driver: local
caddy_config:
driver: local