# syntax=docker/dockerfile:1.7
#
# maestro-nerve backend image.
#
# Same image is deployed as separate Fly process groups: HTTP API and worker.
# Deployed to Fly.io as the `maestro-nerve` app. Same image works locally via
# `docker build -t maestro-nerve . && docker run -p 8080:8080 maestro-nerve`.

FROM python:3.12-slim AS runtime

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PIP_DISABLE_PIP_VERSION_CHECK=1 \
    PIP_NO_COMPILE=1 \
    PORT=8080

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        curl \
        ca-certificates \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install CPU-only torch first so `sentence-transformers` (a transitive dependency)
# resolves against it and pip does not pull the multi-GB CUDA wheel.
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install --index-url https://download.pytorch.org/whl/cpu \
        "torch>=2.0,<3.0"

# Install project dependencies. Copy only what pip needs for the build so that
# source-only edits (scripts, migrations) do not invalidate the dep layer.
COPY pyproject.toml README.md ./
COPY src ./src

RUN --mount=type=cache,target=/root/.cache/pip \
    pip install .

# Runtime assets that are not part of the installed package.
COPY scripts ./scripts
COPY migrations ./migrations

RUN chmod +x scripts/*.sh

# Drop privileges for the running process.
RUN groupadd --system --gid 1000 nerve \
    && useradd  --system --uid 1000 --gid nerve --shell /bin/bash --create-home nerve \
    && chown -R nerve:nerve /app
USER nerve

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD curl --silent --fail "http://localhost:${PORT}/health" || exit 1

CMD ["/app/scripts/start-backend.sh"]
