MEGA-BOQ-WEBAPP/Dockerfile
MEGA INFRA 301d0fff44 MEGA INFRA BOQ Converter — Candy PDF to consultant Excel
Reads our Candy PDF (deterministically, no OCR or model needed) and populates
the consultant's own workbook using their formulas, column layout and PAYMENT
column. Nothing is ever silently overwritten: every disagreement is reported,
can be settled inside the app, and regenerated.

- extract   Candy text PDF -> tree (x-position column detection)
- template  layout detect, sequence align, write, totals, overrides
- validate  qty x rate and children-vs-subtotal reconciliation
- profiles  per-consultant layout profiles, stored on a volume

Shipped with a Dockerfile + docker-compose for Coolify.
2026-10-01 02:32:13 +02:00

60 lines
2 KiB
Docker

# syntax=docker/dockerfile:1
#
# MEGA INFRA · BOQ Converter
# Streamlit web app. Single process, no database, no build step.
FROM python:3.12-slim
# libGL/libglib are what pdfplumber -> pdfminer.six -> Wand/OpenCV chain in;
# without them the container starts and then dies on the first PDF.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libglib2.0-0 libgl1 curl \
&& rm -rf /var/lib/apt/lists/*
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app
# Dependencies first, so a code change does not reinstall the world.
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py run.py ./
COPY boq_engine/ ./boq_engine/
COPY static/ ./static/
COPY .streamlit/ ./.streamlit/
# Run as a non-root user. UID 1000 matches the usual Coolify/Docker convention.
RUN useradd --create-home --uid 1000 --shell /bin/bash megainfra \
&& mkdir -p /data/profiles /app/out \
&& chown -R megainfra:megainfra /app /data
USER megainfra
ENV HOME=/home/megainfra \
BOQ_PROFILES=/data/profiles \
STREAMLIT_BROWSER_GATHER_USAGE_STATS=false \
MPLCONFIGDIR=/tmp/mpl
EXPOSE 8501
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsS http://localhost:8501/_stcore/health || exit 1
# Flags here deliberately override .streamlit/config.toml:
# --server.address 0.0.0.0 the config binds 127.0.0.1 for local dev, which
# is unreachable from outside the container
# --server.enableXsrfProtection false
# Coolify's Traefik sits in front and rewrites the
# origin; Streamlit's origin check then rejects
# the rewritten POST as a forged request
CMD ["streamlit", "run", "app.py", \
"--server.port=8501", \
"--server.address=0.0.0.0", \
"--server.headless=true", \
"--server.enableCORS=false", \
"--server.enableXsrfProtection=false", \
"--browser.gatherUsageStats=false"]