mtg_python_deckbuilder/DOCKER.md

16 KiB
Raw Blame History

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:
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:

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 (optin)

  • Set WEB_VIRTUALIZE=1 to 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 /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):

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=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/Doctors 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:

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=1 keeps the selector visible.
  • WEB_THEME_PICKER_DIAGNOSTICS=1 unlocks 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=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).

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 /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.