|
| 1 | +# DC Deck Builder — Deployment Guide |
| 2 | + |
| 3 | +## Architecture |
| 4 | + |
| 5 | +``` |
| 6 | +[S3 Static Website] |
| 7 | + ↕ WebSocket / HTTP |
| 8 | +[Cloud Run — Flask + game thread] |
| 9 | + - Scales to 0 when idle → ~$0/month at rest |
| 10 | + - WebSocket support via gevent |
| 11 | + - Game state in-memory (one game per container) |
| 12 | +``` |
| 13 | + |
| 14 | +## Prerequisites |
| 15 | + |
| 16 | +1. **GCP project** — enable these APIs: |
| 17 | + ``` |
| 18 | + gcloud services enable run.googleapis.com \ |
| 19 | + artifactregistry.googleapis.com \ |
| 20 | + --project=YOUR_PROJECT_ID |
| 21 | + ``` |
| 22 | +2. **Docker** installed locally |
| 23 | +3. **Terraform >= 1.5** installed |
| 24 | +4. **gcloud CLI** authenticated: `gcloud auth login` |
| 25 | +5. Configure Docker for Artifact Registry: |
| 26 | + ``` |
| 27 | + gcloud auth configure-docker us-central1-docker.pkg.dev |
| 28 | + ``` |
| 29 | + |
| 30 | +--- |
| 31 | + |
| 32 | +## One-time Setup (Terraform) |
| 33 | + |
| 34 | +```bash |
| 35 | +cd terraform |
| 36 | + |
| 37 | +# Create terraform.tfvars |
| 38 | +cat > terraform.tfvars <<EOF |
| 39 | +project_id = "website-489802" |
| 40 | +region = "us-central1" |
| 41 | +EOF |
| 42 | + |
| 43 | +terraform init |
| 44 | +terraform apply |
| 45 | +``` |
| 46 | + |
| 47 | +This creates: |
| 48 | +- Artifact Registry repository |
| 49 | +- Cloud Run service (min 0, max 1 instance) |
| 50 | +- Public IAM binding |
| 51 | + |
| 52 | +--- |
| 53 | + |
| 54 | +## Deploy (build & push) |
| 55 | + |
| 56 | +Run from the project root each time you want to update: |
| 57 | + |
| 58 | +```bash |
| 59 | +# Set your values |
| 60 | +PROJECT_ID="website-489802" |
| 61 | +REGION="us-central1" |
| 62 | +SERVICE="dc-deck-builder" |
| 63 | +IMAGE="${REGION}-docker.pkg.dev/${PROJECT_ID}/${SERVICE}/${SERVICE}" |
| 64 | +TAG=$(git rev-parse --short HEAD 2>/dev/null || echo "latest") |
| 65 | + |
| 66 | +# Build |
| 67 | +docker build -t "${IMAGE}:${TAG}" -t "${IMAGE}:latest" . |
| 68 | + |
| 69 | +# Push |
| 70 | +docker push "${IMAGE}:${TAG}" |
| 71 | +docker push "${IMAGE}:latest" |
| 72 | + |
| 73 | +# Update Cloud Run (or let Terraform handle it) |
| 74 | +gcloud run deploy ${SERVICE} \ |
| 75 | + --image "${IMAGE}:${TAG}" \ |
| 76 | + --region ${REGION} \ |
| 77 | + --project ${PROJECT_ID} |
| 78 | +``` |
| 79 | + |
| 80 | +--- |
| 81 | + |
| 82 | +## Frontend (S3) |
| 83 | + |
| 84 | +The `frontend/` folder is served directly by the Flask backend. For the **standalone S3 website** you already have, update `game.js` line 7: |
| 85 | + |
| 86 | +```javascript |
| 87 | +const SERVER_URL = 'https://dc-deck-builder-35l4saorlq-uc.a.run.app"'; |
| 88 | +``` |
| 89 | + |
| 90 | +Then copy the frontend files to S3: |
| 91 | +```bash |
| 92 | +aws s3 sync frontend/ s3://your-bucket-name/ --delete |
| 93 | +``` |
| 94 | + |
| 95 | +The Cloud Run service already has `cors_allowed_origins="*"` so cross-origin requests from S3 will work. |
| 96 | + |
| 97 | +--- |
| 98 | + |
| 99 | +## Local Development |
| 100 | + |
| 101 | +```bash |
| 102 | +# Install dependencies (no arcade needed for web mode) |
| 103 | +pip install -r requirements.txt |
| 104 | + |
| 105 | +# Run locally |
| 106 | +python web_server.py |
| 107 | + |
| 108 | +# Open browser at http://localhost:8080 |
| 109 | +``` |
| 110 | + |
| 111 | +To test with arcade too (original game): |
| 112 | +```bash |
| 113 | +pip install arcade |
| 114 | +python main.py |
| 115 | +``` |
| 116 | + |
| 117 | +--- |
| 118 | + |
| 119 | +## Cost Estimate |
| 120 | + |
| 121 | +| Scenario | Cost | |
| 122 | +|---|---| |
| 123 | +| Idle (no games running) | **$0** (scales to zero) | |
| 124 | +| 1 hour of play/day | ~$0.01–0.03 | |
| 125 | +| Playing all day every day | ~$0.50–2.00 | |
| 126 | + |
| 127 | +Cloud Run free tier: 180,000 vCPU-seconds + 360,000 GB-seconds per month. |
| 128 | +A 1-hour game uses roughly 3,600 vCPU-seconds → ~50 free hours/month. |
| 129 | + |
| 130 | +--- |
| 131 | + |
| 132 | +## Troubleshooting |
| 133 | + |
| 134 | +**WebSocket not connecting:** |
| 135 | +- Cloud Run supports WebSockets natively; check that `session-affinity` isn't needed (it shouldn't be for single-instance) |
| 136 | +- Check CORS: the S3 URL must be reachable from the frontend |
| 137 | + |
| 138 | +**`arcade` import errors on Cloud Run:** |
| 139 | +- The code conditionally imports arcade — it's not required for the web server |
| 140 | +- Make sure `arcade` is NOT in `requirements.txt` (it isn't) |
| 141 | + |
| 142 | +**Cold start delay (~2–4 s):** |
| 143 | +- Expected with scale-to-zero; the first request after idle takes a few seconds |
| 144 | +- The frontend shows "Connecting…" while this happens |
| 145 | + |
| 146 | +**Game stuck after starting:** |
| 147 | +- Check Cloud Run logs: `gcloud run logs read --service=dc-deck-builder --region=us-central1` |
| 148 | +- The game thread logs to stdout which appears in Cloud Run logs |
0 commit comments