# Kurs-Image zu "Optimierte Entscheidungsfindung mit Python".
#
# Was es ist: eine reproduzierbare Umgebung, in der alle Beispielprogramme
# laufen - ohne dass jemand Solver, BLAS-Bibliotheken und Python-Versionen von
# Hand zusammensuchen muss.
#
# Was es NICHT ist: eine Bauumgebung fuer das Buch. Das PDF braucht pandoc,
# xelatex und inkscape, zusammen ueber ein Gigabyte. Wer das Buch selbst baut,
# ist mit einer lokalen Installation besser bedient (siehe README.md).
#
#   docker build -t or-mit-python .
#   docker run --rm or-mit-python Installationstest.py
#   docker run --rm -it or-mit-python                    # Python-Eingabe
#   docker run --rm -v "$PWD/ausgabe:/buch/output" or-mit-python Excel_Bruecke.py
#
# Zwei Stufen: Die erste baut die Abhaengigkeiten in eine virtuelle Umgebung
# (und braucht dafuer Compiler), die zweite kopiert nur das Ergebnis. Das
# spart im fertigen Image die gesamte Bauumgebung.

# --- Stufe 1: Abhaengigkeiten uebersetzen und einsammeln ---------------------
FROM python:3.12-slim AS bau

# build-essential wird von Paketen gebraucht, die kein passendes Wheel
# mitbringen. Bleibt in dieser Stufe und landet nie im fertigen Image.
RUN apt-get update && apt-get install --no-install-recommends -y \
        build-essential \
    && rm -rf /var/lib/apt/lists/*

ENV PIP_NO_CACHE_DIR=1 \
    PIP_DISABLE_PIP_VERSION_CHECK=1
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# Nur die Abhaengigkeitsbeschreibung kopieren, nicht den Quelltext: So bleibt
# diese Schicht im Cache, solange sich die Abhaengigkeiten nicht aendern.
WORKDIR /buch
COPY pyproject.toml README.md ./

# Die Gruppen aus pyproject.toml. 'figures' fehlt bewusst - es dient dem
# Neuerzeugen der Diagramme, wofuer zusaetzlich Graphviz noetig waere.
#
# ACHTUNG, gewollt: Das Image enthaelt ortools UND highspy, obwohl beide eine
# eigene HiGHS-Kopie mitbringen und sich nicht gemeinsam importieren lassen.
# Der Konflikt wird nicht durch Weglassen geloest, sondern zur Laufzeit durch
# getrennte Prozesse (Kapitel Oekosystem). Ein Image, das nur eines von beiden
# enthaelt, koennte die Haelfte der Beispiele nicht ausfuehren.
RUN pip install ".[finance,large-scale,api,dev]"

# --- Stufe 2: das eigentliche Image -----------------------------------------
FROM python:3.12-slim AS laufzeit

# libgomp1 wird von OR-Tools und HiGHS zur Laufzeit gebraucht (OpenMP) und ist
# im slim-Image nicht enthalten. Ohne es scheitert der erste Solveraufruf mit
# einem 'libgomp.so.1: cannot open shared object file'.
RUN apt-get update && apt-get install --no-install-recommends -y \
        libgomp1 \
    && rm -rf /var/lib/apt/lists/*

COPY --from=bau /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH" \
    PYTHONUNBUFFERED=1 \
    MPLBACKEND=Agg

# Kein root. Die Programme brauchen keine Rechte, und ein Kurs-Image, das als
# root laeuft, ist eine schlechte Angewohnheit, die man weitergibt.
RUN useradd --create-home --uid 1000 kurs
WORKDIR /buch
COPY --chown=kurs:kurs Operations_Research_mit_Python_Version_04_Programme/ ./

# Verzeichnis fuer erzeugte Dateien - als Volume einhaengbar, damit
# Excel-Ausgaben und Diagramme den Container ueberleben. Angelegt wird es
# VOR dem Benutzerwechsel, denn /buch gehoert root.
RUN mkdir -p /buch/output && chown kurs:kurs /buch/output
USER kurs

# Ohne Argument eine Python-Eingabeaufforderung, mit Argument das genannte
# Programm: 'docker run --rm or-mit-python Rucksack.py'
ENTRYPOINT ["python"]
CMD []
