Arag / Dockerfile
AuthorBot
Production hardening: JWT blacklist, TOTP, Pydantic schemas, Prometheus, SSRF fix, CSP, Redis auth, Celery backup β€” 35 items across P0-P5
131d826
Raw
History Blame Contribute Delete
2.65 kB
# ============================================================
# AuthorBot RAG API β€” HuggingFace Spaces Dockerfile
# Entry: app.py β†’ app/main.py (FastAPI)
# Routes: /api/chat/{slug} Β· /api/admin/{slug} Β· /api/super Β· /health
# ============================================================
FROM python:3.11-slim AS builder
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
libmagic1 \
curl \
git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r requirements.txt
# ── Production Stage ──────────────────────────────────────────
FROM python:3.11-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 \
libmagic1 \
curl \
redis-server \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
ENV PYTHONPATH=/app
ENV DATABASE_URL=sqlite+aiosqlite:////data/db.sqlite
ENV REDIS_URL=redis://:authorbotredis@localhost:6379/0
ENV CHROMA_CLIENT_MODE=persistent
ENV CHROMA_PERSIST_DIR=/data/chroma
ENV UPLOAD_STORAGE_PATH=/data/uploads
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
# Copy entire flat project (app/, static/, app.py, requirements.txt)
COPY app/ ./app/
COPY static/ ./static/
COPY app.py .
RUN mkdir -p /data/chroma /data/uploads /data/sessions /data/redis && \
printf 'dir /data/redis\nbind 127.0.0.1\nport 6379\ndaemonize yes\nlogfile /dev/null\nrequirepass authorbotredis\nappendonly yes\nappendfsync everysec\n' > /app/redis-hf.conf
RUN adduser --disabled-password --gecos "" --uid 1000 appuser && \
chown -R appuser:appuser /app /data
USER appuser
# Pre-warm ML models (non-fatal if network unavailable at build time)
RUN python -c "from sentence_transformers import CrossEncoder; CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')" || true
RUN python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')" || true
RUN python -c "from app.main import app; print('App import OK')"
HEALTHCHECK --interval=30s --timeout=10s --start-period=180s --retries=5 \
CMD curl -f http://localhost:7860/health || exit 1
EXPOSE 7860
CMD ["sh", "-c", "mkdir -p /data/chroma /data/uploads /data/sessions /data/redis && redis-server /app/redis-hf.conf && sleep 1 && uvicorn app.main:app --host 0.0.0.0 --port 7860 --workers 1 --loop uvloop --http httptools"]