FROM python:3.12-slim
WORKDIR /site
ENV PYTHONUNBUFFERED=1 PYTHONIOENCODING=utf-8
# Deps: install everything except carson-telemetry from PyPI (it is VENDORED, not
# on PyPI), then pip-install the local copy with its FastAPI extra. Mirrors the
# erwin/leonid/volcker/ussr box-image pattern exactly. A missing vendor tree fails
# the BUILD loudly rather than shipping a silently un-instrumented image — which
# is how starcruiser ran with telemetry off from launch until 2026-07-29.
# `.dockerignore` deliberately does NOT filter vendor/ for the same reason.
COPY app/requirements.txt /site/app/requirements.txt
COPY vendor /site/vendor
RUN grep -v '^carson-telemetry' /site/app/requirements.txt > /tmp/req.txt && \
    pip install --no-cache-dir -r /tmp/req.txt && \
    pip install --no-cache-dir "/site/vendor/carson-telemetry[fastapi]"
COPY app /site/app
COPY templates /site/templates
COPY static /site/static
EXPOSE 8100
# FastAPI is ASGI — gunicorn's default sync WSGI worker returns HTTP 500 on every
# route ("FastAPI.__call__() missing 1 required positional argument: 'send'").
# The -k uvicorn.workers.UvicornWorker flag is MANDATORY and matches the estate
# convention (erwin/leonid/starcruiser/volcker). Found by the erwin deploy health
# gate 2026-07-28.
CMD ["gunicorn", "app.main:app", \
     "-k", "uvicorn.workers.UvicornWorker", "-w", "2", \
     "-b", "0.0.0.0:8100", "--timeout", "120", "--access-logfile", "-"]
