# 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 -p 127.0.0.1:8888:8888 or-mit-python # JupyterLab # docker run --rm or-mit-python Installationstest.py # ein Programm # 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,notebook]" # --- 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/ ./ COPY --chown=kurs:kurs Notebooks_04/ ./Notebooks_04/ # 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 # Ein Startbefehl, zwei Betriebsarten - damit niemand '--entrypoint' braucht: # ohne Argument -> JupyterLab mit den 25 Kapitel-Notebooks # mit Argument -> genau dieses Programm RUN printf '%s\n' \ '#!/bin/sh' \ 'if [ $# -eq 0 ]; then' \ ' exec jupyter lab --ip=0.0.0.0 --port=8888 --no-browser \' \ ' --ServerApp.token= --ServerApp.root_dir=/buch' \ 'fi' \ 'exec python "$@"' \ > /usr/local/bin/starte && chmod +x /usr/local/bin/starte USER kurs EXPOSE 8888 # JupyterLab laeuft ohne Token. Das ist fuer ein Kurs-Image auf dem eigenen # Rechner richtig - deshalb im README die Portfreigabe an 127.0.0.1 binden # und den Container NICHT ins offene Netz stellen. ENTRYPOINT ["/usr/local/bin/starte"] CMD []