Deployment¶
This document describes the Docker Compose topology defined in Sectorwars2102/docker-compose.yml. It is the single source of truth for which services run, how they are wired, and what they need from the environment.
Profiles¶
Compose profiles select which subset of services starts. Multiple profiles can be combined.
| Profile | Services started | Use case |
|---|---|---|
development / default |
database, redis-cache, gameserver, player-client, admin-ui, nginx-gateway, region-manager |
Local development with hot-reload volumes. |
multi-regional |
central-nexus-db, redis-cache, redis-nexus, central-nexus-server, player-client, admin-ui, nginx-gateway, region-manager |
Testing the full multi-region topology. |
production |
central-nexus-db, redis-cache, redis-nexus, central-nexus-server, player-client, admin-ui, nginx-gateway |
Hardened deployment without dev DB or region-manager. |
monitoring |
prometheus, grafana |
Add to any other profile. |
regional-template |
regional-db-template, regional-server-template |
Template definitions used by region-manager to clone a new region. Not started directly. |
Run with e.g.:
docker compose up # default / development
docker compose --profile multi-regional up
docker compose --profile production --profile monitoring up
The compose file has no version: key (modern Compose). Trust docker-compose.yml as the source of truth for the service list.
Networks¶
Three bridge networks segment traffic:
| Network | Subnet | Used by |
|---|---|---|
sectorwars-network |
default bridge | database, redis-cache, gameserver, player-client, admin-ui, nginx-gateway, region-manager |
nexus-network |
${NEXUS_SUBNET:-172.20.0.0/16} |
central-nexus-db, redis-cache, redis-nexus, central-nexus-server, regional-*, nginx-gateway, prometheus, grafana |
regional-network |
${REGIONAL_SUBNET:-172.21.0.0/16} |
central-nexus-server, regional-server-template, nginx-gateway |
redis-cache straddles sectorwars-network and nexus-network so dev and multi-regional services can share it. nginx-gateway is on all three so it can route to any backend.
Volumes¶
All named volumes are local Docker volumes. Grouped roughly by purpose:
- Dev persistence:
postgres_data,postgres_backups,redis_cache_data,gameserver_data,gameserver_logs,nginx_logs. - Multi-regional:
central_nexus_data,redis_nexus_data,nexus_assets,regional_assets,admin_ui_assets,player_client_assets. - Monitoring:
prometheus_data,grafana_data.
Bind mounts worth knowing about:
./services/<svc>:/appongameserver,player-client,admin-uienables live reload by mounting source over the image../services/database/init:/docker-entrypoint-initdb.druns SQL on first boot../services/gameserver/sql/init-central-nexus.sqlinitializes the Nexus DB./var/run/docker.sock:/var/run/docker.sockis mounted intoregion-managerso it can launch sibling containers. Treat this as a privileged surface.
Healthchecks¶
Every long-running service defines a healthcheck:
| Service | Test | Interval / start |
|---|---|---|
database, central-nexus-db, regional-db-template |
pg_isready -U $USER -d $DB |
10 s / 30 s start |
redis-cache, redis-nexus |
redis-cli -a $PWD ping (port 6380 for nexus) |
10 s |
gameserver, central-nexus-server, regional-server-template |
curl -f http://localhost:8080/api/v1/status/health |
30 s / 40 s start |
region-manager |
curl -f http://localhost:8080/health |
30 s |
player-client, admin-ui |
Node http.get('/index.html') returns 200 |
30 s |
Compose uses these for depends_on: condition: service_healthy so the gameserver waits for Postgres + Redis to report healthy before starting.
Environment variables¶
All configuration is environment-driven; secrets live in a .env file at the repo root (gitignored). services/gameserver/src/core/config.py is the authority for what the backend reads.
Required¶
DATABASE_URL— full Postgres URL.JWT_SECRET— must be ≥32 characters; the gameserver refuses to start otherwise (config.pyraisesValueError).SECRET_KEY— generic app secret.ADMIN_USERNAME,ADMIN_PASSWORD— bootstrap admin credentials, hashed with Argon2 on first boot.
OAuth (optional but used in real environments)¶
CLIENT_ID_GITHUB,CLIENT_SECRET_GITHUB— note: notGITHUB_*because GitHub reserves that prefix in Codespaces.GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET.STEAM_API_KEY.
URLs and environment detection¶
API_BASE_URL(defaulthttp://localhost:8080).FRONTEND_URL(defaulthttp://localhost:3000).ENVIRONMENT—development|production|test.DEBUG— toggles/docs,/redoc,/openapi.jsonexposure (gated inmain.py).DEV_ENVIRONMENT,CODESPACE_NAME,GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN— picked up bysettings.detect_environment()to switch between local and Codespaces.
AI / payments / multi-regional¶
OPENAI_API_KEY,ANTHROPIC_API_KEY,OPENAI_MODEL,ANTHROPIC_MODEL,AI_DIALOGUE_ENABLED,AI_PROVIDER_PRIMARY,AI_PROVIDER_SECONDARY,AI_PROVIDER_FALLBACK.PAYPAL_CLIENT_ID,PAYPAL_CLIENT_SECRET,PAYPAL_WEBHOOK_ID,PAYPAL_MODE,PAYPAL_GALACTIC_CITIZEN_PLAN_ID,PAYPAL_REGIONAL_OWNER_PLAN_ID.NEXUS_DB_NAME,NEXUS_DB_USER,NEXUS_DB_PASSWORD,NEXUS_DB_PORT.REGION_NAME,REGION_DB_USER,REGION_DB_PASSWORD,REGION_OWNER_ID,CENTRAL_NEXUS_URL,ENABLE_CROSS_REGIONAL_API,REGIONAL_ISOLATION.
Ports / networking¶
GAMESERVER_PORT (8080), PLAYER_CLIENT_PORT (3000), ADMIN_UI_PORT (3001), REGION_MANAGER_PORT (8081), DB_PORT (5433), REDIS_PORT (6379), REDIS_NEXUS_PORT (6380), HTTP_PORT (80), HTTPS_PORT (443), PROMETHEUS_PORT (9090), GRAFANA_PORT (3002).
A working .env.example lives at Sectorwars2102/.env.example.
Dev vs prod differences¶
Drawn directly from docker-compose.yml:
| Concern | Dev (development / default) |
Prod (production) |
|---|---|---|
| Database | Local database service (Postgres in container) |
central-nexus-db plus per-region DBs |
| Redis | redis-cache only |
redis-cache + redis-nexus for cross-region pub/sub |
| Game server | Single gameserver container with bind-mounted source |
central-nexus-server (read-only image, no source bind), plus regional servers spun up by region-manager |
region-manager |
Present (so you can prototype provisioning) | Absent in production profile; provisioning happens out-of-band |
| FastAPI docs | /docs, /redoc, /openapi.json enabled when DEBUG=true |
Disabled when DEBUG=false (see services/gameserver/src/main.py) |
| CORS | allow_origins=["*"] when DEVELOPMENT_MODE |
Restricted to FRONTEND_URL plus Codespaces / Repl.co wildcards |
| Trusted hosts | ["*"] in dev |
localhost, *.app.github.dev, *.repl.co |
| Nginx | Optional in dev | Required entry point; TLS via mounted certs in services/nginx-gateway/ssl/ |
| Volumes | Bind-mounted source for hot reload | Named volumes for built assets only (player_client_assets, admin_ui_assets) |
| Logging | DEBUG level when DEBUG=true |
INFO level |
docker-compose.yml ships local Postgres containers for both dev and the Nexus. A remote Postgres (e.g. Neon) can be used by overriding DATABASE_URL.
Operational notes¶
- The gameserver's
startup_event(insrc/main.py) runsBase.metadata.create_all, so a fresh DB will be schema-populated on first boot — Alembic migrations are still the source of truth for schema evolution (services/gameserver/alembic/). - A background heartbeat task (
_heartbeat_cleanup_loop) runs every 30 s to evict WebSocket connections idle for more than 5 minutes. - Prometheus scrapes are configured via
monitoring/prometheus.yml(mounted into the prometheus container). Grafana provisioning lives undermonitoring/grafana/.