# LiDAR XYZ tile map ("lidar-maps" image) - see docs/MAPS.md. # # Serves the Web Mercator tile pyramid (OpenStreetMap scheme) rendered from # the pipeline's source tiles, plus the viewing interface and the PDF export. # No PDAL, no GDAL, no GPU: Pillow + pyproj + reportlab are enough (ARM64 included). # # docker compose -f docker-compose.maps.yml up -d --build FROM python:3.12-slim ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris # Pillow >= 11.3: native AVIF encoding/decoding (pipeline tiles and # sub-tiles); pyproj: Lambert 93 -> Web Mercator reprojection without GDAL; # reportlab: printable PDF sheet, pure Python. RUN pip3 install --no-cache-dir \ fastapi \ uvicorn \ "pillow>=11.3" \ pyproj \ "reportlab>=4.0" WORKDIR /app # Only modules that import without numpy/GDAL are loaded (mapserve.py, # tiles.py, mapui.py, index.py for the layer registries, export_pdf.py, # quality.py, progress.py, fetch_ign.py); the processing modules are copied # but never loaded. COPY lidar_pipeline/ ./lidar_pipeline/ # Interface CSS/JS baked into the image: the map code follows the image, # not the tile cache (regenerated on every build). RUN python3 -c "import sys; sys.path.insert(0, '/app'); \ from lidar_pipeline.mapui import write_map_assets, ASSETS_DIRNAME; \ write_map_assets('/app/lidar_pipeline/' + ASSETS_DIRNAME)" RUN groupadd -g 1000 lidar && \ useradd -u 1000 -g lidar -m -s /bin/bash lidar && \ mkdir -p /data/output && \ chown -R lidar:lidar /data # FIXED mmap threshold (1 MiB): large image buffers (tile decoding, ~25 MB) # are returned to the system as soon as they are freed. With glibc's dynamic # threshold they stayed in the heap after the first free and the container's # memory never went back down (OOM on the Pi). ENV LIDAR_OUTPUT_DIR=/data/output \ LIDAR_PORT=8975 \ PYTHONPATH=/app \ MALLOC_MMAP_THRESHOLD_=1048576 USER lidar EXPOSE 8975 CMD ["python3", "-m", "uvicorn", "lidar_pipeline.mapserve:app", "--host", "0.0.0.0", "--port", "8975"]