| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Shortlist Backend β Production Dockerfile | |
| # Multi-stage build for minimal attack surface | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Stage 1: Build dependencies | |
| FROM python:3.12-slim AS builder | |
| WORKDIR /build | |
| # Install build dependencies | |
| RUN apt-get update && \ | |
| apt-get install -y --no-install-recommends gcc && \ | |
| rm -rf /var/lib/apt/lists/* | |
| COPY requirements.txt . | |
| RUN pip install --no-cache-dir --prefix=/install -r requirements.txt | |
| # Stage 2: Production image | |
| FROM python:3.12-slim AS production | |
| # Security: Run as non-root user | |
| RUN groupadd -r shortlist && useradd -r -g shortlist -d /app -s /sbin/nologin shortlist | |
| WORKDIR /app | |
| # Copy only installed packages from builder | |
| COPY --from=builder /install /usr/local | |
| # Copy application code | |
| COPY app/ ./app/ | |
| # Security: Remove unnecessary packages and caches | |
| RUN apt-get update && \ | |
| apt-get install -y --no-install-recommends git && \ | |
| rm -rf /var/lib/apt/lists/* && \ | |
| pip cache purge 2>/dev/null || true | |
| # Security: Set restrictive file permissions | |
| RUN chown -R shortlist:shortlist /app && \ | |
| chmod -R 550 /app | |
| # Create temp directory for repo cloning with restricted permissions | |
| RUN mkdir -p /tmp/shortlist_repos && \ | |
| chown shortlist:shortlist /tmp/shortlist_repos && \ | |
| chmod 700 /tmp/shortlist_repos | |
| # Switch to non-root user | |
| USER shortlist | |
| # Health check | |
| HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ | |
| CMD python -c "import httpx; httpx.get('http://localhost:8000/health').raise_for_status()" || exit 1 | |
| EXPOSE 8000 | |
| # Run with production settings | |
| # - workers: 4 (adjust based on CPU cores) | |
| # - timeout: 120s (repo analysis can take time) | |
| # - limit-concurrency: prevent resource exhaustion | |
| CMD ["uvicorn", "app.main:app", \ | |
| "--host", "0.0.0.0", \ | |
| "--port", "8000", \ | |
| "--workers", "4", \ | |
| "--timeout-keep-alive", "120", \ | |
| "--limit-concurrency", "100", \ | |
| "--no-access-log"] | |