# syntax=docker/dockerfile:1 # ============================================================================= # CRM System v1.0 - Production Dockerfile # Multi-stage build: builder (with build tools) + runtime (slim, non-root) # Base: python:3.12-slim # ============================================================================= # === Stage 1: Builder === # Installs build dependencies (needed for compiling asyncpg, cryptography, etc.) FROM python:3.12-slim AS builder ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 # Build tools (gcc, libpq-dev) — needed for asyncpg + python-jose[cryptography] RUN apt-get update \ && apt-get install -y --no-install-recommends \ build-essential \ libpq-dev \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # Copy ONLY requirements first for optimal layer caching COPY requirements.txt . # Install all production dependencies into a user-local prefix RUN pip install --user --no-cache-dir -r requirements.txt # === Stage 2: Runtime === # Slim image, non-root user, no build tools FROM python:3.12-slim AS runtime ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 \ PATH=/home/appuser/.local/bin:$PATH # Runtime dependencies: libpq5 (for asyncpg), curl (for healthcheck) RUN apt-get update \ && apt-get install -y --no-install-recommends \ libpq5 \ curl \ && rm -rf /var/lib/apt/lists/* \ && groupadd -g 1000 appuser \ && useradd -m -u 1000 -g appuser appuser WORKDIR /app # Copy installed Python packages from builder COPY --from=builder /root/.local /home/appuser/.local # Copy application source (static files included via app/webui/) COPY --chown=appuser:appuser . . # Make prestart.sh executable RUN chmod +x /app/prestart.sh USER appuser # Internal port (Coolify/Traefik terminate SSL on 443 externally) EXPOSE 8000 # Healthcheck: hits the root-level /health endpoint defined in app/main.py # Interval 30s, timeout 10s, 3 retries, 15s start-period (migrations need time) HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \ CMD curl -fsS http://localhost:8000/health || exit 1 # Entrypoint runs DB migrations first, then starts uvicorn as PID 1 ENTRYPOINT ["/app/prestart.sh"]