mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2025-12-16 23:50:12 +01:00
347 lines
16 KiB
Markdown
347 lines
16 KiB
Markdown
# Docker Guide
|
||
|
||
Spin up the MTG Python Deckbuilder inside containers. The image defaults to the Web UI; switch to the CLI/headless runner by flipping environment variables. All commands assume Windows PowerShell.
|
||
|
||
## Build a Deck (Web UI)
|
||
|
||
- Build the image (first run only) and start the `web` service in detached mode:
|
||
|
||
```powershell
|
||
docker compose up --build --no-deps -d web
|
||
```
|
||
|
||
- Open http://localhost:8080 to use the browser experience. First launch seeds data, downloads the latest card catalog, and tags cards automatically (`WEB_AUTO_SETUP=1`, `WEB_TAG_PARALLEL=1`, `WEB_TAG_WORKERS=4` in `docker-compose.yml`).
|
||
|
||
- Stop or restart the service when you're done:
|
||
|
||
```powershell
|
||
docker compose stop web
|
||
docker compose start web
|
||
```
|
||
|
||
Then open http://localhost:8080
|
||
|
||
Volumes are the same as the CLI service, so deck exports/logs/configs persist in your working folder.
|
||
The app serves a favicon at `/favicon.ico` and exposes a health endpoint at `/healthz`.
|
||
Compare view offers a Copy summary button to copy a plain-text diff of two runs. The sidebar has a subtle depth shadow for clearer separation.
|
||
|
||
Web UI feature highlights:
|
||
- Locks: Click a card or the lock control in Step 5; locks persist across reruns.
|
||
- Replace: Enable Replace in Step 5, click a card to open Alternatives (filters include Owned-only), then choose a swap.
|
||
- Permalinks: Copy a permalink from Step 5 or a Finished deck; paste via “Open Permalink…” to restore.
|
||
- Compare: Use the Compare page from Finished Decks; quick actions include Latest two and Swap A/B.
|
||
|
||
Virtualized lists and lazy images (opt‑in)
|
||
- Set `WEB_VIRTUALIZE=1` to enable virtualization in Step 5 grids/lists and the Owned library for smoother scrolling on large sets.
|
||
- Example (Compose):
|
||
```yaml
|
||
services:
|
||
web:
|
||
environment:
|
||
- WEB_VIRTUALIZE=1
|
||
```
|
||
- Example (Docker Hub):
|
||
```powershell
|
||
docker run --rm -p 8080:8080 `
|
||
-e WEB_VIRTUALIZE=1 `
|
||
-v "${PWD}/deck_files:/app/deck_files" `
|
||
-v "${PWD}/logs:/app/logs" `
|
||
-v "${PWD}/csv_files:/app/csv_files" `
|
||
-v "${PWD}/owned_cards:/app/owned_cards" `
|
||
-v "${PWD}/config:/app/config" `
|
||
-e SHOW_DIAGNOSTICS=1 ` # optional: enables diagnostics tools and overlay
|
||
mwisnowski/mtg-python-deckbuilder:latest `
|
||
bash -lc "cd /app && uvicorn code.web.app:app --host 0.0.0.0 --port 8080"
|
||
```
|
||
|
||
### Diagnostics and logs (optional)
|
||
Enable internal diagnostics and a read-only logs viewer with environment flags.
|
||
|
||
- `SHOW_DIAGNOSTICS=1` — adds a Diagnostics nav link and `/diagnostics` tools
|
||
- `SHOW_LOGS=1` — enables `/logs` and `/status/logs?tail=200`
|
||
|
||
Per-face MDFC snapshot (opt-in)
|
||
- `DFC_PER_FACE_SNAPSHOT=1` — write merged MDFC face metadata to `logs/dfc_per_face_snapshot.json`; disable parallel tagging (`WEB_TAG_PARALLEL=0`) if you need the snapshot during setup.
|
||
- `DFC_PER_FACE_SNAPSHOT_PATH=/app/logs/custom_snapshot.json` — optional path override for the snapshot artifact.
|
||
|
||
When enabled:
|
||
- `/logs` supports an auto-refresh toggle with interval, a level filter (All/Error/Warning/Info/Debug), and a Copy button to copy the visible tail.
|
||
- `/status/sys` returns a simple system summary (version, uptime, UTC server time, and feature flags) and is shown on the Diagnostics page when `SHOW_DIAGNOSTICS=1`.
|
||
- Virtualization overlay: press `v` on pages with virtualized grids to toggle per-grid overlays and a global summary bubble.
|
||
|
||
Compose example (web service):
|
||
```yaml
|
||
environment:
|
||
- SHOW_LOGS=1
|
||
- SHOW_DIAGNOSTICS=1
|
||
```
|
||
|
||
```powershell
|
||
docker run --rm -p 8080:8080 `
|
||
-v "${PWD}/deck_files:/app/deck_files" `
|
||
-v "${PWD}/logs:/app/logs" `
|
||
-v "${PWD}/csv_files:/app/csv_files" `
|
||
-v "${PWD}/config:/app/config" `
|
||
-v "${PWD}/owned_cards:/app/owned_cards" `
|
||
mwisnowski/mtg-python-deckbuilder:latest
|
||
```
|
||
|
||
### MDFC merge rollout (staging)
|
||
|
||
The web service now runs the MDFC merge by default. Set `DFC_COMPAT_SNAPSHOT=1` on the web service when you need the legacy unmerged compatibility snapshot (`csv_files/compat_faces/`). Combine this with `python -m code.scripts.refresh_commander_catalog --compat-snapshot` inside the container to regenerate the commander files before smoke testing.
|
||
|
||
Follow the QA steps in `docs/qa/mdfc_staging_checklist.md` after toggling the flag.
|
||
|
||
Compose example:
|
||
|
||
```yaml
|
||
services:
|
||
web:
|
||
environment:
|
||
- DFC_COMPAT_SNAPSHOT=1
|
||
```
|
||
|
||
Verify the refresh inside the container:
|
||
|
||
```powershell
|
||
docker compose run --rm web bash -lc "python -m code.scripts.refresh_commander_catalog"
|
||
```
|
||
|
||
Downstream consumers can diff `csv_files/compat_faces/commander_cards_unmerged.csv` against historical exports during the staging window.
|
||
|
||
### Setup speed: parallel tagging (Web)
|
||
First-time setup or stale data triggers card tagging. The web service uses parallel workers by default.
|
||
|
||
## Run a JSON Config
|
||
|
||
Use the homepage “Run a JSON Config” button or run the same flow in-container:
|
||
|
||
```powershell
|
||
docker compose run --rm `
|
||
-e APP_MODE=cli `
|
||
-e DECK_MODE=headless `
|
||
-e DECK_CONFIG=/app/config/deck.json `
|
||
web
|
||
```
|
||
|
||
- `APP_MODE=cli` routes the entrypoint to the CLI menu.
|
||
- `DECK_MODE=headless` skips prompts and calls `headless_runner`.
|
||
- Mount JSON configs under `config/` so both the UI and CLI can pick them up.
|
||
- Dual-commander support is feature-flagged: set `ENABLE_PARTNER_MECHANICS=1` and pass `--secondary-commander` _or_ `--background` (mutually exclusive) to layer partners/backgrounds into headless runs; Partner With and Doctor/Doctor’s Companion pairings auto-resolve (with opt-out), and `--dry-run` echoes the resolved pairing for verification.
|
||
- Partner suggestions share the same dataset for headless and web flows; set `ENABLE_PARTNER_SUGGESTIONS=1` (and ensure `config/analytics/partner_synergy.json` exists) to expose ranked pairings in the UI and API.
|
||
|
||
Override counts, theme tags, or include/exclude lists by setting the matching environment variables before running the container (see “Environment variables” below).
|
||
|
||
## Initial Setup
|
||
|
||
The homepage “Initial Setup” tile appears when `SHOW_SETUP=1` (enabled in compose). It re-runs:
|
||
|
||
1. Card downloads and color-filtered CSV generation.
|
||
2. Commander catalog rebuild (including multi-face merges).
|
||
3. Tagging and caching.
|
||
|
||
To force a rebuild from the host:
|
||
|
||
```powershell
|
||
docker compose run --rm --entrypoint bash web -lc "python -m code.file_setup.setup"
|
||
```
|
||
|
||
Add `--entrypoint bash ... "python -m code.scripts.refresh_commander_catalog"` when you only need the commander catalog (with MDFC merge and optional compatibility snapshot).
|
||
|
||
## Owned Library
|
||
|
||
Store `.txt` or `.csv` lists in `owned_cards/` (mounted to `/app/owned_cards`). The Web UI uses them for:
|
||
|
||
- Owned-only or prefer-owned builds.
|
||
- The Owned Library management page (virtualized when `WEB_VIRTUALIZE=1`).
|
||
- Alternative suggestions that respect ownership.
|
||
|
||
Use `/owned` to upload files and export enriched lists. These files persist through the `owned_cards` volume.
|
||
|
||
## Browse Commanders
|
||
|
||
`SHOW_COMMANDERS=1` exposes the commander browser tile.
|
||
|
||
- Data lives in `csv_files/commander_cards.csv`.
|
||
- Refresh the catalog (including MDFC merges) from within the container:
|
||
|
||
```powershell
|
||
docker compose run --rm --entrypoint bash web -lc "python -m code.scripts.refresh_commander_catalog"
|
||
```
|
||
|
||
Pass `--compat-snapshot` if you also need an unmerged compatibility CSV under `csv_files/compat_faces/`.
|
||
|
||
## Finished Decks
|
||
|
||
The Finished Decks page reads the `deck_files/` volume for completed builds:
|
||
|
||
- Each run produces CSV, TXT, compliance JSON, and summary JSON sidecars.
|
||
- Locks and replace history persist per deck.
|
||
- Compare view can diff and export summaries.
|
||
|
||
Ensure the deck exports volume remains mounted so these artifacts survive container restarts.
|
||
|
||
## Browse Themes
|
||
|
||
The Themes browser exposes the merged theme catalog with search, filters, and diagnostics.
|
||
|
||
- `ENABLE_THEMES=1` keeps the selector visible.
|
||
- `WEB_THEME_PICKER_DIAGNOSTICS=1` unlocks uncapped synergies, extra metadata, and `/themes/metrics`.
|
||
- Regenerate the catalog manually:
|
||
|
||
```powershell
|
||
docker compose run --rm --entrypoint bash web -lc "python -m code.scripts.build_theme_catalog"
|
||
```
|
||
|
||
Advanced options (e.g., `EDITORIAL_*` variables) live in `.env.example`.
|
||
|
||
## Random Build
|
||
|
||
Enable the Surprise/Reroll flow by setting:
|
||
|
||
- `RANDOM_MODES=1` to expose backend random endpoints.
|
||
- `RANDOM_UI=1` to show the Random Build tile.
|
||
- Optional tunables: `RANDOM_MAX_ATTEMPTS`, `RANDOM_TIMEOUT_MS`, `RANDOM_PRIMARY_THEME`, `RANDOM_SEED`, and auto-fill flags.
|
||
|
||
Headless parity is available by pairing `APP_MODE=cli` with `DECK_MODE=headless` and the same random variables.
|
||
|
||
## Diagnostics
|
||
|
||
`SHOW_DIAGNOSTICS=1` unlocks `/diagnostics` for system summaries, feature flags, and performance probes. Highlights:
|
||
|
||
- `/healthz` returns `{status, version, uptime_seconds}` for external monitoring.
|
||
- Press `v` on pages with virtualized grids (when `WEB_VIRTUALIZE=1`) to toggle the range overlay.
|
||
- `WEB_AUTO_ENFORCE=1` (optional) applies bracket enforcement automatically after each build.
|
||
|
||
## View Logs
|
||
|
||
`SHOW_LOGS=1` enables the logs tile and `/logs` interface:
|
||
|
||
- Tail the container log with filtering and copy-to-clipboard.
|
||
- `/status/logs?tail=200` offers a lightweight JSON endpoint.
|
||
- Raw files live under `logs/` on the host; rotate or archive them as needed.
|
||
|
||
## Environment variables (Docker quick reference)
|
||
|
||
See `.env.example` for the full catalog. Common knobs:
|
||
|
||
### Core mode and networking
|
||
|
||
| Variable | Default | Purpose |
|
||
| --- | --- | --- |
|
||
| `APP_MODE` | `web` | Switch between Web UI (`web`) and CLI (`cli`). |
|
||
| `DECK_MODE` | _(unset)_ | `headless` auto-runs the headless builder when the CLI starts. |
|
||
| `DECK_CONFIG` | `/app/config/deck.json` | JSON config file or directory (auto-discovery). |
|
||
| `HOST` / `PORT` / `WORKERS` | `0.0.0.0` / `8080` / `1` | Uvicorn binding when `APP_MODE=web`. |
|
||
|
||
### Partner mechanics & suggestions
|
||
|
||
| Variable | Default | Purpose |
|
||
| --- | --- | --- |
|
||
| `ENABLE_PARTNER_MECHANICS` | `0` | Unlock partner/background commander inputs for headless runs and Step 2 of the web UI. |
|
||
| `ENABLE_PARTNER_SUGGESTIONS` | `0` | Serve partner/background/Doctor suggestion chips based on `config/analytics/partner_synergy.json` (auto-regenerated when missing; override path with `PARTNER_SUGGESTIONS_DATASET`). |
|
||
|
||
### Homepage visibility & UX
|
||
|
||
| Variable | Default | Purpose |
|
||
| --- | --- | --- |
|
||
| `SHOW_SETUP` | `1` | Show the Initial Setup card. |
|
||
| `SHOW_LOGS` | `1` | Enable the View Logs tile and endpoints. |
|
||
| `SHOW_DIAGNOSTICS` | `1` | Enable Diagnostics tools and overlays. |
|
||
| `SHOW_COMMANDERS` | `1` | Expose the commander browser. |
|
||
| `ENABLE_THEMES` | `1` | Keep the theme selector and themes explorer visible. |
|
||
| `WEB_VIRTUALIZE` | `1` | Opt-in to virtualized lists/grids for large result sets. |
|
||
| `ALLOW_MUST_HAVES` | `1` | Enable include/exclude enforcement in Step 5. |
|
||
| `SHOW_MUST_HAVE_BUTTONS` | `0` | Surface the must include/exclude buttons and quick-add UI (requires `ALLOW_MUST_HAVES=1`). |
|
||
| `THEME` | `dark` | Initial UI theme (`system`, `light`, or `dark`). |
|
||
| `WEB_STAGE_ORDER` | `new` | Build stage execution order: `new` (creatures→spells→lands) or `legacy` (lands→creatures→spells). |
|
||
| `WEB_IDEALS_UI` | `slider` | Ideal counts interface: `slider` (range inputs with live validation) or `input` (text boxes with placeholders). |
|
||
|
||
### Random build controls
|
||
|
||
| Variable | Default | Purpose |
|
||
| --- | --- | --- |
|
||
| `RANDOM_MODES` | _(unset)_ | Enable random build endpoints. |
|
||
| `RANDOM_UI` | _(unset)_ | Show the Random Build homepage tile. |
|
||
| `RANDOM_MAX_ATTEMPTS` | `5` | Retry budget for constrained random rolls. |
|
||
| `RANDOM_TIMEOUT_MS` | `5000` | Per-attempt timeout in milliseconds. |
|
||
| `RANDOM_REROLL_THROTTLE_MS` | `350` | Minimum ms between reroll requests (client guard). |
|
||
| `RANDOM_STRUCTURED_LOGS` | `0` | Emit structured JSON logs for random builds. |
|
||
| `RANDOM_TELEMETRY` | `0` | Enable lightweight timing/attempt counters. |
|
||
| `RANDOM_PRIMARY_THEME` / `RANDOM_SECONDARY_THEME` / `RANDOM_TERTIARY_THEME` | _(blank)_ | Override theme slots for random runs. |
|
||
| `RANDOM_SEED` | _(blank)_ | Deterministic seed. |
|
||
| `RANDOM_AUTO_FILL` | `1` | Allow automatic backfill of missing theme slots. |
|
||
|
||
### Automation & performance
|
||
|
||
| Variable | Default | Purpose |
|
||
| --- | --- | --- |
|
||
| `WEB_AUTO_SETUP` | `1` | Auto-run data setup when artifacts are missing or stale. |
|
||
| `WEB_AUTO_REFRESH_DAYS` | `7` | Refresh `cards.csv` if older than N days. |
|
||
| `WEB_TAG_PARALLEL` | `1` | Use parallel workers during tagging. |
|
||
| `WEB_TAG_WORKERS` | `4` | Worker count for parallel tagging. |
|
||
| `WEB_AUTO_ENFORCE` | `0` | Re-export decks after auto-applying compliance fixes. |
|
||
| `WEB_THEME_PICKER_DIAGNOSTICS` | `1` | Enable theme diagnostics endpoints. |
|
||
|
||
### Paths and data overrides
|
||
|
||
| Variable | Default | Purpose |
|
||
| --- | --- | --- |
|
||
| `CSV_FILES_DIR` | `/app/csv_files` | Point the app at an alternate dataset (e.g., test snapshots). |
|
||
| `DECK_EXPORTS` | `/app/deck_files` | Override where the web UI looks for exports. |
|
||
| `OWNED_CARDS_DIR` / `CARD_LIBRARY_DIR` | `/app/owned_cards` | Override owned library directory. |
|
||
| `CARD_INDEX_EXTRA_CSV` | _(blank)_ | Inject a synthetic CSV into the card index for testing. |
|
||
|
||
### Supplemental themes
|
||
|
||
| Variable | Default | Purpose |
|
||
| --- | --- | --- |
|
||
| `DECK_ADDITIONAL_THEMES` | _(blank)_ | Comma/semicolon separated list of supplemental themes for headless builds (JSON exports also include the camelCase `userThemes` alias and `themeCatalogVersion` metadata; either alias is accepted on import). |
|
||
| `THEME_MATCH_MODE` | `permissive` | Controls fuzzy theme resolution (`strict` blocks unresolved inputs). |
|
||
|
||
### Random rate limiting (optional)
|
||
|
||
| Variable | Default | Purpose |
|
||
| --- | --- | --- |
|
||
| `RATE_LIMIT_ENABLED` | `0` | Enable server-side rate limiting for random endpoints. |
|
||
| `RATE_LIMIT_WINDOW_S` | `10` | Rolling window in seconds. |
|
||
| `RATE_LIMIT_RANDOM` | `10` | Max random attempts per window. |
|
||
| `RATE_LIMIT_BUILD` | `10` | Max full builds per window. |
|
||
| `RATE_LIMIT_SUGGEST` | `30` | Max suggestion calls per window. |
|
||
|
||
Advanced editorial and theme-catalog knobs (`EDITORIAL_*`, `SPLASH_ADAPTIVE`, etc.) are documented inline in `docker-compose.yml` and `.env.example`.
|
||
|
||
## Shared volumes
|
||
|
||
| Host path | Container path | Contents |
|
||
| --- | --- | --- |
|
||
| `deck_files/` | `/app/deck_files` | CSV/TXT exports, summary JSON, compliance reports. |
|
||
| `logs/` | `/app/logs` | Application logs and taxonomy snapshots. |
|
||
| `csv_files/` | `/app/csv_files` | Card datasets, commander catalog, tagging flags. |
|
||
| `config/` | `/app/config` | JSON configs, bracket policy, card list overrides. |
|
||
| `owned_cards/` | `/app/owned_cards` | Uploaded inventory files for owned-only flows. |
|
||
|
||
## Maintenance commands
|
||
|
||
Run ad-hoc tasks by overriding the entrypoint:
|
||
|
||
```powershell
|
||
# Theme catalog rebuild
|
||
docker compose run --rm --entrypoint bash web -lc "python -m code.scripts.build_theme_catalog"
|
||
|
||
# Snapshot taxonomy (writes logs/taxonomy_snapshots/)
|
||
docker compose run --rm --entrypoint bash web -lc "python -m code.scripts.snapshot_taxonomy"
|
||
|
||
# Preview the MDFC commander diff
|
||
docker compose run --rm --entrypoint bash web -lc "python -m code.scripts.preview_dfc_catalog_diff"
|
||
```
|
||
|
||
Use the `--compat-snapshot` or other script arguments as needed.
|
||
|
||
## Troubleshooting
|
||
|
||
- **Container starts but UI stays blank:** check `/healthz` and `/logs` (enable with `SHOW_LOGS=1`), then inspect the `logs/` volume.
|
||
- **Files missing on the host:** ensure the host directories exist before starting Compose; Windows will create empty folders if the path is invalid.
|
||
- **Long first boot:** dataset downloads and tagging can take several minutes the first time. Watch progress at `/setup`.
|
||
- **Random build hangs:** lower `RANDOM_MAX_ATTEMPTS` or raise `RANDOM_TIMEOUT_MS`, and confirm your theme overrides are valid slugs via `/themes/`.
|
||
- **Commander catalog outdated:** rerun the refresh command above or delete `csv_files/.tagging_complete.json` to force a full rebuild on next start.
|