| # syntax=docker/dockerfile:1 | |
| # | |
| # Hugging Face Spaces (Docker SDK) image for the CardioScan inference server. | |
| # | |
| # Spaces conventions: | |
| # * Container must listen on the port declared in `README.md` (`app_port`). | |
| # * Container is started as user `user` (UID 1000), not root. | |
| # * /data is the only writable location persisted across restarts (we don't | |
| # need persistence β checkpoints ship inside the image). | |
| # | |
| # Build context expected by `scripts/deploy-space.sh`: | |
| # / | |
| # βββ Dockerfile (this file) | |
| # βββ README.md (HF Spaces metadata) | |
| # βββ inference_server/ (FastAPI app + requirements.txt) | |
| # βββ model_training/ | |
| # βββ src/ (only the package; notebooks excluded) | |
| # βββ notebooks/results/ (.pth checkpoints + manifest + metrics) | |
| FROM python:3.11-slim | |
| ENV PYTHONDONTWRITEBYTECODE=1 \ | |
| PYTHONUNBUFFERED=1 \ | |
| PIP_NO_CACHE_DIR=1 \ | |
| PIP_DISABLE_PIP_VERSION_CHECK=1 \ | |
| HF_HOME=/app/.cache/huggingface \ | |
| TORCH_HOME=/app/.cache/torch \ | |
| XDG_CACHE_HOME=/app/.cache | |
| # System deps for Pillow / scientific Python wheels. | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| libgomp1 \ | |
| ca-certificates \ | |
| curl \ | |
| && rm -rf /var/lib/apt/lists/* | |
| # HF Spaces requires the runtime user to be UID 1000. | |
| RUN useradd --create-home --uid 1000 user | |
| WORKDIR /app | |
| # Install Python deps first so layer caches when only code/weights change. | |
| COPY --chown=user:user inference_server/requirements.txt /app/inference_server/requirements.txt | |
| RUN pip install --upgrade pip && \ | |
| pip install --extra-index-url https://download.pytorch.org/whl/cpu \ | |
| torch==2.4.1 torchvision==0.19.1 && \ | |
| pip install -r /app/inference_server/requirements.txt | |
| # Copy the actual code and weights. | |
| COPY --chown=user:user inference_server/ /app/inference_server/ | |
| COPY --chown=user:user model_training/src/ /app/model_training/src/ | |
| COPY --chown=user:user model_training/notebooks/results/ /app/model_training/notebooks/results/ | |
| # Pre-create writable cache dirs owned by `user`. | |
| RUN mkdir -p /app/.cache/torch /app/.cache/huggingface && chown -R user:user /app | |
| USER user | |
| # Spaces routes traffic to whatever app_port we declared in README.md (7860). | |
| ENV PORT=7860 \ | |
| LOG_LEVEL=INFO \ | |
| MODEL_USE_TTA=true \ | |
| ALLOWED_ORIGIN_REGEX="https://([a-z0-9-]+\\.)*lovable\\.app|https://([a-z0-9-]+\\.)*lovableproject\\.com|https://([a-z0-9-]+\\.)*hf\\.space|http://localhost(:\\d+)?|http://127\\.0\\.0\\.1(:\\d+)?" | |
| EXPOSE 7860 | |
| # server.py expects to be importable from /app/inference_server. | |
| WORKDIR /app/inference_server | |
| CMD ["sh", "-c", "uvicorn server:app --host 0.0.0.0 --port ${PORT}"] | |