Spaces:
Running
Running
| # AlphaBrief API β FastAPI + LangGraph + the MCP tool server in one container. | |
| # | |
| # One image serves three things that are usually three deployments: the HTTP | |
| # surface, the agent orchestrator, and the MCP server the agents call (spawned | |
| # in-container over stdio). That is what makes the free tiers viable β a single | |
| # container on Cloud Run's always-free allowance, or a Hugging Face Docker Space | |
| # on port 7860 with no card at all. | |
| # | |
| # Built from the REPOSITORY ROOT, not from apps/api. Hugging Face Spaces builds | |
| # `./Dockerfile` with the repository as its context and offers no way to point it | |
| # elsewhere, so the paths below are root-relative and `make docker` uses the same | |
| # context. One Dockerfile, built identically everywhere β a second, host-specific | |
| # copy would drift, and it would drift silently until a deploy failed. | |
| # | |
| # docker build -t alphabrief-api -f apps/api/Dockerfile . | |
| # docker run --rm -p 7860:7860 --env-file .env alphabrief-api | |
| FROM python:3.12-slim-bookworm AS base | |
| ENV PYTHONDONTWRITEBYTECODE=1 \ | |
| PYTHONUNBUFFERED=1 \ | |
| PIP_NO_CACHE_DIR=1 \ | |
| PIP_DISABLE_PIP_VERSION_CHECK=1 | |
| # curl is used by the container healthcheck only. | |
| RUN apt-get update \ | |
| && apt-get install -y --no-install-recommends curl \ | |
| && rm -rf /var/lib/apt/lists/* | |
| # ---------------------------------------------------------------- deps ------ | |
| FROM base AS deps | |
| WORKDIR /build | |
| COPY apps/api/pyproject.toml apps/api/README.md ./ | |
| COPY apps/api/app ./app | |
| # --root-user-action=ignore: this is a throwaway build stage, so installing as | |
| # root is correct here and pip's "use a virtualenv" advice does not apply. The | |
| # flag silences the warning instead of leaving it in every build log. | |
| RUN pip install --no-cache-dir --root-user-action=ignore . | |
| # --------------------------------------------------------------- runtime ---- | |
| FROM base AS runtime | |
| # Run as a fixed non-root uid 1000. Several hosts (Koyeb, Cloud Run, and | |
| # container platforms that refuse root) either require this or behave better | |
| # with it, so the same image deploys anywhere without a rebuild. | |
| RUN useradd --create-home --uid 1000 alphabrief | |
| COPY --from=deps /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages | |
| COPY --from=deps /usr/local/bin /usr/local/bin | |
| WORKDIR /home/alphabrief/app | |
| COPY --chown=alphabrief:alphabrief apps/api/pyproject.toml apps/api/README.md ./ | |
| COPY --chown=alphabrief:alphabrief apps/api/app ./app | |
| USER alphabrief | |
| ENV PORT=7860 \ | |
| PYTHONPATH=/home/alphabrief/app \ | |
| HOME=/home/alphabrief \ | |
| MCP_TRANSPORT=stdio \ | |
| DATABASE_URL=sqlite:////home/alphabrief/alphabrief.db | |
| EXPOSE 7860 | |
| HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ | |
| CMD curl -fsS "http://127.0.0.1:${PORT}/health" || exit 1 | |
| # Cloud Run injects $PORT; Spaces expects 7860. Honour whichever is set. | |
| CMD ["sh", "-c", "exec uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-7860} --workers 1 --timeout-keep-alive 75"] | |