Dies ist ein maschinell übersetzter Text und kann Fehler enthalten!
Ein Image mit Dockerfile erstellen
Hier erstellen Sie ein Image aus einer Flask-Anwendung und testen es mit docker run. Sie sind fertig, wenn die App antwortet und Sie überprüft haben, dass die lokale .env-Datei außerhalb des neuen Images bleibt. Die Testanwendung benötigt weder GitHub noch eine externe API.
Vor dem Build-Vorgang
Sie müssen ein Image erstellen und nachweisen, dass eine Containerinstanz aus diesem Image antwortet. Sie benötigen [[Docker Level 1 - Einstieg|installiertes Docker]] und müssen in der Lage sein, einen Container zu starten und zu untersuchen, wie unter [[Verwendung von Containern Level 1 - Starte und untersuche einen Container|Starte und untersuche einen Container]] gezeigt wird. Falls keine Flask-Anwendung vorhanden ist, verwenden Sie die Testanwendung unten. Arbeiten Sie im Projektordner auf der Linux-VM, wo sich sowohl app.py als auch alle vorlagen und anderen Projektdateien befinden.
Falls das Projekt in einem Codearchiv liegt, zeigt [[Git in der Terminal Level 1 - Clone, Commit und Push|Git in der Terminal]], wie Sie es auf die VM klonen. Sie können die Dateien auch im Texteditor der VM erstellen. Verwenden Sie pwd und ls, um sicherzustellen, dass Sie sich im richtigen Ordner befinden. Erstellen Sie kein Image aus einem leeren Ordner oder aus der Shell des Proxmox-Gastgebers.
Beginne zuerst mit einer kleinen Test-App
Falls deine App noch nicht auf die VM migriert wurde, kannst du dich mit einem minimalistischen Dockerfile an einer Minimal-App üben. Erstelle einen Ordner mit mkdir min-app und cd min-app, und erstelle eine app.py mit nano:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Hallo aus dem Container!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Erstelle anschließend die requirements.txt und die Dockerfile wie unten gezeigt. Sobald das Build funktioniert, machst du dasselbe für deine eigene App.
Erstellen Sie die Datei requirements.txt im selben Verzeichnis. Diese Datei enthält eine Liste der Python-Pakete, die in das Image installiert werden sollen. Für die einfache Anwendung aus Abschnitt 1 von Flask, die nur Flask verwendet, lautet der Inhalt wie folgt:
Flask
Verwendet die App andere Drittanbieter-Bibliotheken, müssen diese ebenfalls dort mit den richtigen Paketnamen aufgeführt sein, beispielsweise requests. Dateien wie .venv werden nicht zur Installation der Pakete kopiert; Docker installiert sie neu aus dieser Liste. Versionen können gesperrt werden, zum Beispiel durch paketname==version, wenn Sie überprüft haben, welche Versionen die App verwendet.
Erstellen Sie auch eine .dockerignore vor dem ersten Build. Dies verhindert, dass lokale Geheimnisse, der Verlauf von Git und die lokale Python-Umgebung in das Image kopiert werden:
.env
.git
__pycache__/
.venv/
app-data/
Füge auch die Datei „.env`` in die Datei „.gitignore``, falls Sie Git verwenden. Falls die Ignorierungsdateien bereits Inhalte enthalten, fügen Sie fehlende Regeln hinzu, anstatt die Dateien zu ersetzen. Verwenden Sie [[Git in der Konsole Stufe 5 – .gitignore und Geheimnisse|.gitignore und Geheimnisse], um das Tracking vor dem Teilen von Code zu überprüfen.”
Ein Image mit einer Dockerfile erstellen
docker build erstellt das Paket. docker run erzeugt einen Container aus diesem Paket und startet ihn. Das Bauen allein führt nicht zur Ausführung der Anwendung. Siehe [[Docker Level 0 - Was ist Docker|Level 0]], falls die Unterscheidung zwischen Image und Container noch einmal erklärt werden muss.
Eine Dockerfile beschreibt die Schritte, die Docker zum Bau eines Images verwenden soll. Jede Zeile hat eine bestimmte Funktion:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
Docker führt das Build schrittweise aus. COPY und RUN können Dateisystemebenen hinzufügen, während unter anderem CMD beschreibt, wie der Container gestartet werden soll. Docker kann frühere Bilergebnisse aus einem Zwischenspeicher (Build-Cache) wiederverwenden. Wenn ein Schritt neu gebaut werden muss, müssen auch die nachfolgenden Schritte erneut ausgeführt werden.
Daher kopieren wir zunächst nur requirements.txt, bevor COPY . . erfolgt: Die zeitaufwändige Installation wird vor dem Quellcode durchgeführt, der sich häufig ändert:
flowchart TB
L1["Basissubstrat: python:3.12-slim"] --> L2["Arbeitsverzeichnis: /app"]
L2 --> L3["requirements.txt kopieren"]
L3 --> L4["Pakete mit pip installieren"]
L4 --> L5["Quellcode kopieren"] COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
Wenn sich requirements.txt ändert, muss Docker die Pakete neu installieren. Das ist erwünscht: das neue Paket soll tatsächlich im Image enthalten sein. Wenn nur der Quellcode geändert wird, kann Docker die fertige Installationsschicht verwenden und von COPY . . aus weiterbauen.
Wenn Docker einen Port veröffentlicht, leitet Docker den Verkehr an das Programm in dem Container weiter. Das Programm muss daher auf dem Netzwerk des Containers lauschen, nicht nur auf 127.0.0.1, was „dieser Container“ bedeutet. Wenn das Programm nur auf 127.0.0.1 lauscht, können andere Maschinen es über den Docker-Port nicht erreichen.
Flask-Beispiel
Flask muss auf allen Netzwerkschnittstellen (0.0.0.0) lauschen, wenn es in einem Container läuft. 0.0.0.0 bedeutet, dass Flask Anfragen an allen Netzwerkadaptern innerhalb des Containers annimmt. Ersetzen Sie die vorhandene Startblöcke in app.py durch:
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=False)
Dies ist eine Übungsumgebung mit dem Entwicklungsserver von Flask. Bevor die Lösung in der Produktion eingesetzt wird, muss sie mit einem geeigneten WSGI-Server ausgeführt werden; siehe Flask: Produktionsumgebung.
EXPOSE 5000 beschreibt den Port, den die App verwendet; es veröffentlicht den Port nicht allein. Das übernimmt das Argument -p 127.0.0.1:5000:5000 im folgenden Befehl. Bauen und starten:
docker build -t min-app:latest .
docker run -d --name min-app -p 127.0.0.1:5000:5000 min-app:latest
docker logs -f min-app
Drücken Sie Strg+C, um die Log-Anzeige zu beenden. Der Container fährt weiter.
Test von der VM selbst aus:
curl http://127.0.0.1:5000
Sie erhalten den Inhalt aus der Hauptroute der App zurück. Bei -p 127.0.0.1:5000:5000 bedeutet 127.0.0.1:5000 Port 5000 auf dem Server, aber nur für Programme auf dem Server selbst. Die letzte Zahl ist die Portnummer innerhalb des Containers. Wenn es nicht funktioniert, prüfen Sie zuerst docker ps, die Logs und ob der Port korrekt veröffentlicht wurde.
Mit 127.0.0.1 davor ist der Port gegenüber dem Netzwerk gesperrt, sodass keine anderen Maschinen während des Builds und Testens auf die App zugreifen können. Dies ist ein sicheres Standardverhalten für eine App in Entwicklung. Ohne 127.0.0.1 (-p 5000:5000) lauscht der Port auf allen Netzwerkschnittstellen des Servers. Das benötigen Sie erst dann, wenn eine andere Maschine oder ein Proxy auf die App zugreifen soll, siehe Level 3.
Kontrollpunkt: Eigenes Image funktioniert
curl http://127.0.0.1:5000 sollte die Hauptseite der App anzeigen. Für die Testapp lautet die Antwort Hallo aus dem Container!. Erkläre, was docker build erstellt hat und was docker run gestartet hat. Bei Fehlern liest du das Protokoll (Log), bevor du weitergehst.
Stelle sicher, dass .env außerhalb bleibt
Für diese Überprüfung brauchst du keinen echten Schlüssel. Falls das Projekt noch keine .env hat, kannst du sie mit PIGGY_TEST=unbedenklicher_Testwert erstellen. Eine vorhandene Datei beibehalten; überschreibe deine Werte nicht.
- Prüfe, ob sich
.envsowohl in der.dockerignoreals auch in der.gitignorebefindet. - Wenn du Git verwendest, führe die Prüfungen aus der [Übung zu .gitignore|.gitignore-øvelsen]. Ignorierte Dateien sollten zuvor auch nicht verfolgt worden sein.
- Erstelle das Image neu und prüfe diesen Pfad, ohne den Inhalt auszugeben:
# Build the Docker image for the minimal app with tag latest
docker build -t min-app:latest .
# Run a temporary container that checks if /.env does not exist in /app and prints a message accordingly
docker run --rm --entrypoint sh min-app:latest -c 'test ! -e /app/.env && echo ".env exists nicht in /app"'
Erwartetes Ergebnis ist .env exists nicht in /app. Falls die Meldung nicht erscheint, untersuchen Sie die Ignorierungsdatei, bevor Sie das Image teilen. Dies prüft den Dateipfad im fertigen Dateisystem des neuen Images. Es aktualisiert keine alten Images, andere Geheimnisdateien oder direkt in Code oder der Dockerfile geschriebene Werte. Ersetzen Sie einen echten Schlüssel zuerst, wenn dieser zuvor geteilt wurde.
Wenn der Build oder die App fehlschlägt
Bei einem ModuleNotFoundError prüfst Du die requirements.txt und baust neu. Bei Fehlern beim Herunterladen des Basisimages oder von Python-Paketen testest Du das Netzwerk mit [[Feilsokingsmetode Level 1 - Systematisk feilsiking|Fehlerbehebungsmethode]]. Bei fehlender HTTP-Antwort liest Du docker logs min-app und kontrollierst die Flask-Adresse und Portzuordnung.
Nächstes Schritt
Zeige die Antwort der App und die Überprüfung von .env. Erkläre, was in der Dockerfile beschrieben wird, was beim Build erstellt wird und was docker run startet. Fahren Sie mit Docker - Anwendung veröffentlichen fort. Wenn Sie den Start und das Aktualisieren in einer Compose-Datei beschreiben möchten, ist Anwendung mit Compose ausführen und aktualisieren eine optionale Vertiefung.
Compose und Aktualisierung finden sich nun unter Anwendung mit Compose ausführen und aktualisieren.
Die Speicherung wird in Daten außerhalb des Containers bewahren; die Compose-Anwendung findet sich unter Anwendung mit Compose ausführen und aktualisieren.
Das API-Rezept befindet sich jetzt auf der Seite Umgebungsvariable und API-Schlüssel und ist optional.