# GigLez — production image for the live "simple mode" API. # Serves: FastAPI upload/map UI + statistical device-category identification. FROM python:3.10-slim # Faster, quieter, unbuffered logs in containers. ENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PIP_NO_CACHE_DIR=1 WORKDIR /app # Dependencies first for layer caching — only re-runs when reqs change. COPY requirements-prod.txt ./ RUN pip install --no-cache-dir -r requirements-prod.txt # Application code + assets the live path needs. COPY src/ ./src/ COPY static/ ./static/ COPY templates/ ./templates/ COPY config/ ./config/ COPY models/category_classifier.joblib ./models/category_classifier.joblib # Seed data: the static rtl_433 protocol table (read-only) and an initial # capture store. When /app/data is mounted as a *named volume*, Docker seeds # the empty volume from these baked files on first run, then persists writes # to captures_simple.json across restarts. COPY data/rtl_433_protocols.json data/captures_simple.json data/weather_sensors_found.txt ./data/ # Run as a non-root user. RUN useradd --create-home --uid 10001 giglez \ && chown -R giglez:giglez /app USER giglez EXPOSE 8000 # Container-native healthcheck hits the app's /health endpoint. HEALTHCHECK --interval=30s --timeout=3s --start-period=15s --retries=3 \ CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/health').status==200 else 1)" # Serve with uvicorn (module app object), not the __main__ dev banner. CMD ["uvicorn", "src.api.main_simple:app", "--host", "0.0.0.0", "--port", "8000"]