Files
gps-denied-onboard/Dockerfile
T
Yuzviak 78dcf7b4e7 fix: post-audit — runtime bugs, functional gaps, docs, hardening
Phase A — Runtime bugs:
  - SSE: add push_event() method to SSEEventStreamer (was missing, masked by mocks)
  - MAVLink: satellites_visible=10 (was 0, triggers ArduPilot failsafe)
  - MAVLink: horiz_accuracy=sqrt(P[0,0]+P[1,1]) per spec (was sqrt(avg))
  - MAVLink: MEDIUM confidence → fix_type=3 per solution.md (was 2)

Phase B — Functional gaps:
  - handle_user_fix() injects operator GPS into ESKF with noise=500m
  - app.py uses create_vo_backend() factory (was hardcoded SequentialVO)
  - ESKF: Mahalanobis gating on satellite updates (rejects outliers >5σ)
  - ESKF: public accessors (position, quaternion, covariance, last_timestamp)
  - Processor: no more private ESKF field access

Phase C — Documentation:
  - README: correct API endpoints, CLI command, 40+ env vars documented
  - Dockerfile: ENV prefixes match pydantic-settings (DB_, SATELLITE_, MAVLINK_)
  - tech_stack.md marked ARCHIVED (contradicts solution.md)

Phase D — Hardening:
  - JWT auth middleware (AUTH_ENABLED=false default, verify_token on /flights)
  - TLS config env vars (AUTH_SSL_CERTFILE, AUTH_SSL_KEYFILE)
  - SHA-256 tile manifest verification in SatelliteDataManager
  - AuthConfig, ESKFSettings, MAVLinkConfig, SatelliteConfig in config.py

Also: conftest.py shared fixtures, download_tiles.py, convert_to_trt.py scripts,
config wiring into app.py lifespan, config-driven ESKF, calculate_precise_angle fix.

Tests: 196 passed / 8 skipped. Ruff clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 18:27:35 +03:00

62 lines
2.1 KiB
Docker

# ---------------------------------------------------------------------------
# GPS-Denied Onboard — Production Dockerfile
# ---------------------------------------------------------------------------
# Build: docker build -t gps-denied-onboard .
# Run: docker run -p 8000:8000 gps-denied-onboard
#
# Jetson Orin Nano Super deployment: use base image
# nvcr.io/nvidia/l4t-pytorch:r36.2.0-pth2.1-py3
# and replace python:3.11-slim with that image.
# ---------------------------------------------------------------------------
FROM python:3.11-slim AS builder
WORKDIR /build
# System deps for OpenCV headless + numpy compilation
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
libgl1 \
libglib2.0-0 \
&& rm -rf /var/lib/apt/lists/*
COPY pyproject.toml .
# Install only the package metadata (no source yet) to cache deps layer
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -e "." --no-build-isolation
# ---------------------------------------------------------------------------
FROM python:3.11-slim AS runtime
WORKDIR /app
# Runtime system deps (OpenCV headless needs libGL + libglib)
RUN apt-get update && apt-get install -y --no-install-recommends \
libgl1 \
libglib2.0-0 \
&& rm -rf /var/lib/apt/lists/*
# Copy installed packages from builder
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
# Copy application source
COPY src/ src/
COPY pyproject.toml .
# Runtime environment
ENV PYTHONPATH=/app/src \
DB_URL=sqlite+aiosqlite:////data/flights.db \
SATELLITE_TILE_DIR=/data/satellite_tiles \
MAVLINK_CONNECTION=udp:127.0.0.1:14550
# Data volume: database + satellite tiles
VOLUME ["/data"]
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
CMD ["uvicorn", "gps_denied.app:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]