# ============================================================================= # LabGraph — Multi-stage Dockerfile # Stages: base → development → production # docker-compose uses target: development for all services # ============================================================================= # ----------------------------------------------------------------------------- # base — shared OS deps, non-root user, Python dependencies # ----------------------------------------------------------------------------- FROM python:3.12-slim AS base ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 # curl: required by docker-compose web healthcheck (curl http://localhost:8000/api/health/) # nmap: required by python-nmap discovery tasks (Phase 2) # libpq-dev + build-essential: required to compile psycopg[binary] RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ libpq-dev \ curl \ nmap \ && rm -rf /var/lib/apt/lists/* RUN groupadd --gid 1000 appuser && \ useradd --uid 1000 --gid appuser --shell /bin/bash --create-home appuser WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt # ----------------------------------------------------------------------------- # development — volume-mounted source, no CMD (docker-compose provides it) # ----------------------------------------------------------------------------- FROM base AS development RUN pip install watchdog EXPOSE 8000 # ----------------------------------------------------------------------------- # production — source baked in, runs as non-root, gunicorn CMD # ----------------------------------------------------------------------------- FROM base AS production COPY . . RUN python manage.py collectstatic --noinput USER appuser EXPOSE 8000 CMD ["gunicorn", "config.wsgi:application", \ "--bind", "0.0.0.0:8000", \ "--workers", "4", \ "--worker-class", "gthread", \ "--threads", "2", \ "--timeout", "120", \ "--access-logfile", "-", \ "--error-logfile", "-"]