16 KiB
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
webservice in detached mode:
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=4indocker-compose.yml). -
Stop or restart the service when you're done:
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=1to enable virtualization in Step 5 grids/lists and the Owned library for smoother scrolling on large sets. - Example (Compose):
services: web: environment: - WEB_VIRTUALIZE=1 - Example (Docker Hub):
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/diagnosticstoolsSHOW_LOGS=1— enables/logsand/status/logs?tail=200
Per-face MDFC snapshot (opt-in)
DFC_PER_FACE_SNAPSHOT=1— write merged MDFC face metadata tologs/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:
/logssupports an auto-refresh toggle with interval, a level filter (All/Error/Warning/Info/Debug), and a Copy button to copy the visible tail./status/sysreturns a simple system summary (version, uptime, UTC server time, and feature flags) and is shown on the Diagnostics page whenSHOW_DIAGNOSTICS=1.- Virtualization overlay: press
von pages with virtualized grids to toggle per-grid overlays and a global summary bubble.
Compose example (web service):
environment:
- SHOW_LOGS=1
- SHOW_DIAGNOSTICS=1
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:
services:
web:
environment:
- DFC_COMPAT_SNAPSHOT=1
Verify the refresh inside the container:
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:
docker compose run --rm `
-e APP_MODE=cli `
-e DECK_MODE=headless `
-e DECK_CONFIG=/app/config/deck.json `
web
APP_MODE=cliroutes the entrypoint to the CLI menu.DECK_MODE=headlessskips prompts and callsheadless_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=1and pass--secondary-commanderor--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-runechoes the resolved pairing for verification. - Partner suggestions share the same dataset for headless and web flows; set
ENABLE_PARTNER_SUGGESTIONS=1(and ensureconfig/analytics/partner_synergy.jsonexists) 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:
- Card downloads and color-filtered CSV generation.
- Commander catalog rebuild (including multi-face merges).
- Tagging and caching.
To force a rebuild from the host:
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:
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=1keeps the selector visible.WEB_THEME_PICKER_DIAGNOSTICS=1unlocks uncapped synergies, extra metadata, and/themes/metrics.- Regenerate the catalog manually:
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=1to expose backend random endpoints.RANDOM_UI=1to 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:
/healthzreturns{status, version, uptime_seconds}for external monitoring.- Press
von pages with virtualized grids (whenWEB_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=200offers 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). |
ENABLE_CARD_DETAILS |
0 |
Show card detail pages with similar card recommendations at /cards/<name>. |
SIMILARITY_CACHE_ENABLED |
1 |
Use pre-computed similarity cache for fast card detail pages. |
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:
# 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
/healthzand/logs(enable withSHOW_LOGS=1), then inspect thelogs/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_ATTEMPTSor raiseRANDOM_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.jsonto force a full rebuild on next start.