Zum Inhalt

Caching und Multistage

Ziel

In diesem Projekt geht es um den Cache und Multistage-Builds. Sie werden:

  • Cache-busting zu Ihrem Vorteil nutzen
  • einen Multistage-Build erstellen und bauen

Hilfsmittel

  • Versuchen Sie, die unten stehenden Aufgaben mit Hilfe der Folien und des Cheatsheets eigenständig zu lösen.
  • Sollten Sie dabei Probleme haben, finden Sie bei jeder Aufgabe einen ausklappbaren Block, in dem der Lösungsweg beschrieben wird.

Vorbereitung

Stellen Sie sicher, dass Sie sich immernoch im Ordner mein-erstes-image aus dem vorherigen Hands-On befinden.

Aufgabe 1 - Layer und Caching

1.1: Bauen mit Cache

  • Bauen Sie das Image erneut und beobachten Sie die Ausgabe.
  • Für alle Layer wird der Cache verwendet. Es wird nichts erneut gebaut.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
  • Führen Sie erneut

    docker build -t demo01 .
    
    aus.

  • Die Ausgabe enthält bei jedem Layer CACHED, z.B.:

     => CACHED [5/7] COPY requirements.txt .
    

1.2: Cache-busting in app.py

  • Verändern Sie in app.py den String "Web App with Python Flask!".
  • Bauen Sie das Image erneut.
  • Betrachten Sie die Ausgabe. Es konnte nun nicht mehr in jedem Schritt der Cache verwendet werden.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
  • Verändern Sie den Rückgabewert in Zeile 7 in app.py zu:
        return 'Hello World from Docker demo'
    
  • Führen Sie erneut docker build -t demo01 . aus.
  • Die Ausgabe enthält nun bei Schritt 7 nicht mehr CACHED, z.B.:
     => [7/7] COPY app.py .
    
  • Das Layer musste erneut gebaut werden.

1.3: Cache-busting durch neue Systemabhängigkeiten

  • Fügen Sie zu den bisherigen Systemabhängigkeiten python3 und python3-pip noch ein weiteres Paket nano hinzu.
  • Bauen Sie das Image erneut.
  • Der Build dauert nun wieder länger, da die Systemabhängigkeiten erneut installiert werden müssen und der Cache nicht mehr verwendet werden konnte.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
  • Ändern Sie das Dockerfile zu:
        [...]
        RUN apt-get update && apt-get install -y \
            python3 \
            python3-pip \
            nano \
        && rm -rf /var/lib/apt/lists/*
        [...]
    
  • Führen Sie erneut
    docker build -t demo01 .
    
    aus.
  • Die Layer mussten erneut gebaut werden.

Aufgabe 2 - Multistage-Build

2.1: requirements.dev.txt anlegen

Erstellen Sie im Ordner mein-erstes-image eine Datei requirements.dev.txt mit dem Inhalt:

pylint
pytest

2.2: Dockerfile zu Multistage-Build erweitern

Wir wollen nun, basierend auf dem bisherigen, minimalen Image, weitere Entwicklungsabhängigkeiten installieren. Mit diesen könnte man in einer CI/CD-Pipeline Unit-/Integration-Tests und Code-Linting umsetzen. Die Abhängigkeiten sollen aber nicht im bisherigen, minimalen Image enthalten sein.

  • Geben Sie der bisherigen Stage den Namen runtime.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
  • Ändern Sie das Dockerfile zu:
        FROM ubuntu:20.04 as runtime
    
        RUN apt-get update && apt-get install -y \
        [...]
    
  • Erstellen Sie eine zweite Stage dev_environment, die basierend auf der ersten Stage weitere Abhängigkeiten aus der requirement.dev.txt installiert. Beachten Sie hierbei, dass vorher der User auf root und danach wieder auf app-runner-user gesetzt werden muss, da nur der Root-User die Rechte für die Installationen hat.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
  • Ändern Sie das Dockerfile zu:
        [...]
        CMD ["python3", "app.py"]
    
        ## Zweite Stage
        FROM runtime as dev_environment
    
        USER root
        COPY requirements.dev.txt .
        RUN python3 -m pip install -r requirements.dev.txt
    
        USER app-runner-user
    

2.3: Multistage-Build bauen

Bauen Sie nun beide Stages.

Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
  • Wenn Sie alle Stages bauen möchten, können Sie das, wie bisher, mit folgendem Befehl tun:
    docker build -t demo01_dev .
    

Bauen Sie nun nur die erste Stage.

Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
  • Bauen Sie die erste Stage mit dem Namen runtime, wie folgt:
    docker build -t demo01 --target runtime .
    

Sie haben nun erfolgreich mit dem Cache und Multistage-Builds gearbeitet. Durch die Einbeziehung des Caches in den Erstellungsprozesses eines Dockerfiles lässt sich die Build-Zeit erheblich minimieren. Multistage-Builds eignen sich hervorragend um die Image-Größe zu minimieren.