Ctrl K
ComunidadGuías…

docker-compose.yml

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
services:
  api:
    build:
      context: .
      dockerfile: api/Dockerfile
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    env_file:
      - .env
    environment:
      - TZ=America/New_York
    volumes:
      # Mount the whole api/ source so uvicorn --reload picks up .py edits live —
      # no docker cp, no image drift. Nested mounts below layer on top.
      - ./api:/app
      - ./api/data:/app/data
      - ./api/templates:/app/templates
      - ./web:/app/static
      # App submodules (spire, noodle): api/app_paths.py puts apps/*/api on
      # sys.path; their web/ joins the "/" static mount, their templates _tmpl.
      - ./apps:/app/apps
      - ./graphify-out:/app/graphify-out:ro
      - ./mtg/data:/app/mtg/data
      - ./nightfall-incident:/app/nightfall
      # KEPT ON PURPOSE though the rmapi binary is gone (2026-09-17). This volume
      # holds a real authenticated reMarkable device token (`rmapi.conf`, last
      # written 2026-04-28) -- re-pairing a device is a manual, physical act, so
      # the token is not something to throw away to tidy a compose file. Left
      # MOUNTED rather than merely declared, because a declared-but-unmounted
      # compose volume counts as unused and `docker volume prune` would eat it.
      # Costs ~1.5KB. Restore the feature by putting the builder stage back.
      - rmapi-auth:/root/.config/rmapi
      - gcal-auth:/root/.config/gcal
    # nightfall-src/ is the GAME'S SOURCE tree (354MB, 29k entries incl. node_modules).
    # Nothing at runtime reads it -- only the BUILT output is served (index.html,
    # static/, wai-*.js, audio/), and webpack runs on the HOST, never in here. But it
    # rode along inside the ./nightfall-incident bind mount, and uvicorn --reload
    # rglob()s the whole /app tree looking for *.py, so those 29k entries were 85% of
    # a walk that ran 4x a second: 0.21s per pass on a 0.25s interval = 44% of a core,
    # permanently, for 8 days straight. An empty tmpfs over that one path masks it out
    # of the container (34,187 entries walked -> 5,177) and costs 0 bytes, since
    # nothing ever writes there. Docker mounts shallowest-first, so this lands ON TOP
    # of the ./nightfall-incident bind above it; the host copy is untouched.
    tmpfs:
      - /app/nightfall/nightfall-src
    # The docker log had no size limit and lived as long as the container. It is
    # capped (3 x 10MB, oldest dropped) -- the access lines in it carried noodle
    # slugs and draft tokens until api/log_masking.py (security audit 2026-10-14).
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  # Always-on GLaDOS voice (CPU Piper). Built separately from the hosaka repo:
  #   docker build -f ~/src/hosaka/Dockerfile.piper -t hosaka-piper:latest ~/src/hosaka
  # No torch, glados baked into the image. Keeps /hosaka's glados live even when
  # the home GPU box is off. The api container reaches it by service name over
  # the compose network (TTS_PIPER_UPSTREAM defaults to hosaka-piper:8123); no
  # ports are published -- only api talks to it.
  hosaka-piper:
    image: hosaka-piper:latest
    restart: unless-stopped
    volumes:
      # Pronunciation lexicon synced from the home box (scripts/sync_lexicon.sh,
      # rsync --inplace). Single-file bind mount + hosaka's Lexicon mtime
      # hot-reload => live pronunciation updates with no restart. The host file
      # must exist before the container starts (else docker creates a dir);
      # seed it with the first sync. Read-only: the container only reads it.
      - /srv/hosaka-piper/lexicon.json:/opt/hosaka/.local/share/hosaka/lexicon.json:ro

volumes:
  rmapi-auth:
  gcal-auth: