document deck summary DFC badges, exporter annotations, and per-face metadata across README/DOCKER/release notes record completion of all MDFC roadmap follow-ups and add the authoring guide for multi-face CSV entries wire in optional DFC_PER_FACE_SNAPSHOT env support, exporter regression tests, and diagnostics updates noted in the changelog
9.6 KiB
Docker Guide
Run the MTG Deckbuilder (CLI and Web UI) in Docker with persistent volumes and optional headless mode.
Quick start
PowerShell (recommended)
docker compose build
docker compose run --rm mtg-deckbuilder
From Docker Hub (PowerShell)
docker run -it --rm `
-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" `
mwisnowski/mtg-python-deckbuilder:latest
Web UI (new)
The web UI runs the same deckbuilding logic behind a browser-based interface.
PowerShell (recommended)
docker compose up --build --no-deps -d 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 Hub (PowerShell) example:
docker run --rm `
-p 8080:8080 `
-e SHOW_LOGS=1 -e SHOW_DIAGNOSTICS=1 -e ENABLE_THEMES=1 -e THEME=system `
-e SPLASH_ADAPTIVE=1 -e SPLASH_ADAPTIVE_SCALE="1:1.0,2:1.0,3:1.0,4:0.6,5:0.35" ` # optional experiment
-e RANDOM_MODES=1 -e RANDOM_UI=1 -e RANDOM_MAX_ATTEMPTS=5 -e RANDOM_TIMEOUT_MS=5000 `
-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" `
mwisnowski/mtg-python-deckbuilder:latest `
bash -lc "cd /app && uvicorn code.web.app:app --host 0.0.0.0 --port 8080"
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.
Configure via environment variables on the web service:
WEB_TAG_PARALLEL=1|0— enable/disable parallel tagging (default: 1)WEB_TAG_WORKERS=<N>— number of worker processes (default: 4 in compose)
If parallel initialization fails, the service falls back to sequential tagging and continues.
From Docker Hub (PowerShell)
If you prefer not to build locally, pull mwisnowski/mtg-python-deckbuilder:latest and run uvicorn:
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}/owned_cards:/app/owned_cards" `
-v "${PWD}/config:/app/config" `
mwisnowski/mtg-python-deckbuilder:latest `
bash -lc "cd /app && uvicorn code.web.app:app --host 0.0.0.0 --port 8080"
Health check:
GET http://localhost:8080/healthz -> { "status": "ok", "version": "dev", "uptime_seconds": 123 }
Theme preference reset (client-side): use the header’s Reset Theme control to clear the saved browser preference; the server default (THEME) applies on next paint.
Random Modes (alpha) and test dataset override
Enable experimental Random Modes and UI controls in Web runs by setting:
services:
web:
environment:
- RANDOM_MODES=1
- RANDOM_UI=1
- RANDOM_MAX_ATTEMPTS=5
- RANDOM_TIMEOUT_MS=5000
For deterministic tests or development, you can point the app to a frozen dataset snapshot:
services:
web:
environment:
- CSV_FILES_DIR=/app/csv_files/testdata
Taxonomy snapshot (maintainers)
Capture the current bracket taxonomy into an auditable JSON file inside the container:
docker compose run --rm web bash -lc "python -m code.scripts.snapshot_taxonomy"
Artifacts appear under ./logs/taxonomy_snapshots/ on your host via the mounted volume.
To force a new snapshot even when the content hash matches the latest, pass --force to the module.
Volumes
/app/deck_files↔./deck_files/app/logs↔./logs/app/csv_files↔./csv_files/app/owned_cards↔./owned_cards(owned cards lists: .txt/.csv)- Optional:
/app/config↔./config(JSON configs for headless)
Interactive vs headless
- Interactive: attach a TTY (compose run or
docker run -it) - Headless auto-run:
docker compose run --rm -e DECK_MODE=headless mtg-deckbuilder - Headless with JSON config:
docker compose run --rm ` -e DECK_MODE=headless ` -e DECK_CONFIG=/app/config/deck.json ` mtg-deckbuilder
Common env vars
- DECK_MODE=headless
- DECK_CONFIG=/app/config/deck.json
- DECK_COMMANDER, DECK_PRIMARY_CHOICE
- DECK_ADD_LANDS, DECK_FETCH_COUNT
- DECK_TAG_MODE=AND|OR (combine mode used by the builder)
Web UI tuning env vars
- WEB_TAG_PARALLEL=1|0 (parallel tagging on/off)
- WEB_TAG_WORKERS= (process count; set based on CPU/memory)
- WEB_VIRTUALIZE=1 (enable virtualization)
- SHOW_DIAGNOSTICS=1 (enables diagnostics pages and overlay hotkey
v) - RANDOM_MODES=1 (enable random build endpoints)
- RANDOM_UI=1 (show Surprise/Theme/Reroll/Share controls)
- RANDOM_MAX_ATTEMPTS=5 (cap retry attempts)
- (Upcoming) Multi-theme inputs: once UI ships, Random Mode will accept
primary_theme,secondary_theme,tertiary_themefields; current backend already supports the cascade + diagnostics. - RANDOM_TIMEOUT_MS=5000 (per-build timeout in ms)
Testing/determinism helper (dev):
- CSV_FILES_DIR=csv_files/testdata — override CSV base dir to a frozen set for tests
Manual build/run
docker build -t mtg-deckbuilder .
docker run -it --rm `
-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" `
mtg-deckbuilder
Troubleshooting
- No prompts? Use
docker compose run --rm(notup) or add-ittodocker run - Files not saving? Verify volume mounts and that folders exist
- Headless not picking config? Ensure
./configis mounted to/app/configandDECK_CONFIGpoints to a JSON file - Owned-cards prompt not seeing files? Ensure
./owned_cardsis mounted to/app/owned_cards
Tips
- Use
docker compose run, notup, for interactive mode - Exported decks appear in
deck_files/ - JSON run-config is exported only in interactive runs; headless skips it