Vier Minuten für eine geänderte Zeile
Ein Team ändert eine Zeile im Code eines Shops. Der Build dauert vier Minuten, weil er alle Bibliotheken neu lädt.
Ein anderes Team ändert dieselbe Zeile und wartet eine Sekunde. Beide haben eine Build-Datei geschrieben. Sie haben die Schritte in anderer Reihenfolge geschrieben.
Am Ende dieser Lektion
Notiz
Ich kann ein Dockerfile schreiben und sagen, welche Schritte nach einer Änderung neu laufen.
Schlüsselbegriffe
| Begriff | Was er bedeutet |
|---|---|
| Dockerfile | eine Textdatei mit Schritten, die ein Image baut |
| Basis-Image | das Image, von dem ein Build ausgeht |
| Layer | das gespeicherte Ergebnis eines Build-Schritts |
| Cache | gespeicherte Layer, die ein Build wiederverwendet |
| Build | ein Image bauen, indem man die Schritte ausführt |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Was das Lab nicht kann
Notiz
Das docker des Labs lehnt es ab, ein Image zu bauen oder zu laden: Ein Build führt Schritte mit Rechten auf dem Rechner aus. Wir haben die Dockerfiles dieser Lektion auf unserem eigenen Rechner gebaut. Sie lesen sie, sehen, was ein Image im Container hinterlässt, und prüfen Ihre Datei in der Aufgabe. Für einen echten Build nutzen Sie Ihren Rechner.
Ein Dockerfile ist eine Liste von Schritten
Jede Zeile beginnt mit einem Anweisungswort. FROM nennt das Basis-Image. COPY bringt Dateien hinein. RUN führt beim Bauen einen Befehl aus. CMD sagt, was beim Start eines Containers läuft.
Docker liest die Zeilen von oben. Hier ist ein kleiner Shop so geschrieben.
Ein Dockerfile für einen kleinen Python-Shop
FROM python:3.12-alpine
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]
Der Startordner, gesetzt von WORKDIR
docker inspect --format '{{.Config.WorkingDir}}' cacheHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das Signal zum Stoppen, gesetzt von STOPSIGNAL
docker inspect --format '{{.Config.StopSignal}}' webHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Beispiel: was jede Anweisung hinterlässt
| Anweisung | Was sie beim Build tut | Wo man sie später sieht |
|---|---|---|
| FROM | geht von einem Basis-Image aus | Config.Image nennt das Image |
| WORKDIR | setzt den Ordner der nächsten Schritte | Config.WorkingDir, /data bei cache |
| EXPOSE | nennt die Tür, die das Programm nutzt | Config.ExposedPorts, 80/tcp bei web |
| STOPSIGNAL | sagt, wie man das Programm zum Stoppen bittet | Config.StopSignal, SIGQUIT bei web |
| COPY und RUN | fügen Dateien hinzu und führen Befehle aus | je ein neuer Layer |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Jeder Schritt macht einen Layer
Ein Build speichert das Ergebnis jedes Schritts als Layer. Die Layer liegen gestapelt, und ein Image ist der ganze Stapel. Ein Layer ändert sich nicht mehr, wenn er einmal gemacht ist.
Ein Container legt einen dünnen Layer obenauf, in den er schreibt. docker diff listet, was in diesem obersten Layer liegt.
Beispiel: die Layer des Shop-Images
| Schritt | Größe auf unserem Testrechner |
|---|---|
| Das Basis-Image python:3.12-alpine | etwa 48 MB im größten Layer |
| WORKDIR /app | 8 kB |
| COPY requirements.txt . | 12 kB |
| RUN pip install ... | 10,6 MB |
| COPY app.py . | 12 kB |
| CMD ["python", "app.py"] | 0 B |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Eine Datei in web selbst schreiben
docker exec web touch /tmp/layer-demo.txtHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Sie im obersten Layer finden
docker diff web | grep layer-demoHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Ein Layer wird wiederverwendet, wenn oben nichts wechselt
Bevor Docker einen Schritt ausführt, stellt es eine Frage. Ist es derselbe Schritt mit denselben Dateien wie beim letzten Mal, und war alles darüber auch gleich? Wenn ja, nutzt es den gespeicherten Layer wieder. Das ist der Cache.
Der erste Schritt, der abweicht, läuft neu. Alle folgenden auch. Setzen Sie nach oben, was sich am seltensten ändert.
Reihenfolge 1: erst alles kopieren
FROM python:3.12-alpine
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
CMD ["python", "app.py"]
Beispiel: app.py ändern, dann neu bauen
| Schritt | Reihenfolge 1 | Reihenfolge 2 (das erste Dockerfile oben) |
|---|---|---|
| WORKDIR /app | im Cache | im Cache |
| COPY requirements.txt . | nicht in dieser Reihenfolge | im Cache |
| COPY . . | läuft neu | nicht in dieser Reihenfolge |
| RUN pip install ... | läuft neu, 11 Sekunden | im Cache |
| COPY app.py . | nicht in dieser Reihenfolge | läuft neu, unter einer Sekunde |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein häufiger Irrtum
Warnung
Viele glauben, Docker wiederhole nur die Zeile, die sie geändert haben. Es wiederholt diesen Schritt und jeden Schritt danach. Kopieren Sie zuerst die Datei mit Ihrer Bibliotheksliste und installieren Sie, dann kopieren Sie Ihren eigenen Code. Der langsame Schritt bleibt dann im Cache.
Weiterführend
Schreiben Sie das Dockerfile für eine kleine eigene Seite. Gehen Sie von nginx:1.27-alpine aus, kopieren Sie eine einzige index.html nach /usr/share/nginx/html und fügen Sie nichts hinzu.
Bauen Sie es auf einem Rechner mit Docker zweimal. Der zweite Build sollte bei jedem Schritt CACHED zeigen.