Spaces:
Running
Running
| # Docker Compose — RoverDevKit webapp | |
| # | |
| # One-command boot for the dockerized tradespace tool. Build context | |
| # is the repo root so the multi-stage Dockerfile under | |
| # `webapp/Dockerfile` can reach the package source plus the | |
| # `data/` and `reports/` artifacts that get baked into the image. | |
| # | |
| # Usage from the repo root: | |
| # | |
| # docker compose -f webapp/docker-compose.yml up --build | |
| # | |
| # Then open http://localhost:8000. | |
| # | |
| # This is the single-process production-style topology: one uvicorn | |
| # container serves both the FastAPI API and the React SPA off | |
| # `ROVERDEVKIT_STATIC_DIR=/app/static`. The Vite dev server is | |
| # **not** part of the compose file — for live frontend reload use | |
| # `make webapp-dev`, which boots backend on :8000 and the Vite dev | |
| # server on :5173 with proxying. | |
| services: | |
| webapp: | |
| build: | |
| # Repo root, so COPY can reach `pyproject.toml`, `roverdevkit/`, | |
| # `data/`, `reports/`, and `webapp/` in a single context. | |
| context: .. | |
| dockerfile: webapp/Dockerfile | |
| image: roverdevkit/webapp:dev | |
| container_name: roverdevkit-webapp | |
| ports: | |
| - "8000:8000" | |
| environment: | |
| # CORS: open to the local docker host. Override at deploy time | |
| # (HF Spaces / Fly.io) by passing your hosted origin via | |
| # ROVERDEVKIT_CORS_ORIGINS. | |
| ROVERDEVKIT_CORS_ORIGINS: "http://localhost:8000,http://127.0.0.1:8000" | |
| # Static frontend mount (set inside the Dockerfile by default | |
| # but echoed here so it's discoverable from `docker inspect`). | |
| ROVERDEVKIT_STATIC_DIR: "/app/static" | |
| healthcheck: | |
| # The /healthz route returns 200 once the artifact loaders have | |
| # had a chance to touch the disk. 30s of startup grace covers | |
| # the first-ever surrogate bundle load on a slow filesystem. | |
| test: ["CMD-SHELL", "python -c \"import urllib.request, sys; sys.exit(0 if urllib.request.urlopen('http://localhost:8000/healthz', timeout=2).status == 200 else 1)\""] | |
| interval: 30s | |
| timeout: 5s | |
| retries: 3 | |
| start_period: 30s | |
| restart: unless-stopped | |