# ── Stage 1: Kafka binaries ────────────────────────────────────────────────── FROM apache/kafka:3.9.0 AS kafka-src # ── Stage 2: Frontend build ─────────────────────────────────────────────────── FROM node:20-alpine AS frontend-build WORKDIR /build COPY services/frontend/package.json services/frontend/package-lock.json ./ RUN npm install --prefer-offline COPY services/frontend . RUN npm run build # ── Stage 3: Main runtime ───────────────────────────────────────────────────── FROM python:3.12-slim # System packages RUN apt-get update && apt-get install -y --no-install-recommends \ openjdk-21-jre-headless \ nginx \ supervisor \ postgresql \ redis-server \ procps \ && rm -rf /var/lib/apt/lists/* # Kafka JARs + scripts from official image (JVM-based, no native binary issues) COPY --from=kafka-src /opt/kafka /opt/kafka ENV PATH="/opt/kafka/bin:$PATH" # Java home for PySpark — symlink resolves across amd64/arm64 RUN ln -s "$(dirname $(dirname $(readlink -f $(which java))))" /opt/java ENV JAVA_HOME=/opt/java # Python packages RUN pip install --no-cache-dir \ "fastapi>=0.111" \ "uvicorn[standard]" \ asyncpg \ "redis[asyncio]>=5.0" \ "kafka-python-ng>=2.2" \ prometheus-client \ "pydantic>=2.7" \ "mlflow>=2.13" \ psycopg2-binary \ "pyspark==3.5.3" \ "numpy>=1.26" \ "httpx>=0.27" # Pre-download Spark Kafka connector JAR so streaming.py starts offline RUN python -c "\ from pyspark.sql import SparkSession; \ SparkSession.builder \ .config('spark.jars.packages', 'org.apache.spark:spark-sql-kafka-0-10_2.12:3.5.3') \ .config('spark.ui.enabled', 'false') \ .getOrCreate().stop()" # Frontend static files COPY --from=frontend-build /build/dist /app/frontend/dist # App sources COPY services/api /app/api COPY services/spark-jobs /app/spark-jobs COPY services/event-simulator /app/event-simulator # HF infra configs + scripts COPY infra/hf /app/infra/hf RUN chmod +x /app/infra/hf/*.sh # nginx: replace default config RUN rm -f /etc/nginx/sites-enabled/default COPY infra/hf/nginx.conf /etc/nginx/conf.d/cinematch.conf # Pre-seeded bootstrap data (committed to repo after local `make bootstrap`) COPY data /app/data # Runtime dirs RUN mkdir -p /var/lib/postgresql/data \ /var/lib/kafka-logs \ /var/log/supervisor \ /var/log/kafka \ && chown postgres:postgres /var/lib/postgresql/data WORKDIR /app EXPOSE 7860 CMD ["/app/infra/hf/init.sh"]