Dockerfile
Ziel
In diesem Projekt geht es um das Dockerfile und das Erstellen von eigenen Images. Sie werden:
- ein eigenes Dockerfile für einen Service erstellen
- einen zweiten Service in das Dockerfile hinzufügen und die Services verbinden
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.
Aufgabe 1 - Ein erstes Dockerfile erstellen
- Erstellen Sie einen neuen Unterordner
mein-erstes-image
des Workspace-Ordners/home/coder/workspace
. - Erstellen Sie in dem Ordner ein
Dockerfile
mit folgenden Eigenschaften:- Baseimage:
ubuntu:20.04
- Entrypoint:
["/bin/echo", "Hallo"]
- Command:
["Welt"]
- Baseimage:
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Öffnen Sie den Explorer von VSCode mit
Strg + B
oder alternativ per Klick auf das Datei-Icon (über der Lupe) in der linken Leiste. - Erstellen Sie über den Explorer einen neuen Ordner mit dem Namen
mein-erstes-image
. - Erstellen Sie in dem Ordner eine Datei mit dem Namen
Dockerfile
. - Fügen Sie folgenden Inhalt in die Datei ein:
FROM ubuntu:20.04 ENTRYPOINT ["/bin/echo", "Hallo"] CMD ["Welt"]
Aufgabe 2 - Ein erstes Image bauen
2.1: Image bauen
Bauen Sie im Terminal aus dem Dockerfile
ein Image mit dem Namen demo01
.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Öffnen Sie ein Terminal (Menü > Terminal > New Terminal).
- Wechseln Sie mit
cd mein-erstes-image
in den erstellten Ordner.cd
steht fürChange Directory
. - Führen Sie
pwd
aus.pwd
liefert Ihnen das aktuelle Verzeichnis. Sie sollten die Ausgabe/home/coder/workspace/mein-erstes-image
erhalten. - Sollten Sie die Ausgabe nicht erhalten, wechseln Sie in das Verzeichnis mit
cd /home/coder/workspace/mein-erstes-image
. - Bauen Sie nun das Image mit:
docker build -t demo01 .
- Sie sollten nach dem fertigen Build eine Ausgabe sehen, die ähnlich zu folgender aussieht:
Step 3/3 : CMD ["Welt"] ---> Running in fdef47b21535 Removing intermediate container fdef47b21535 ---> 6296257370ba Successfully built 6296257370ba Successfully tagged demo01:latest
2.2: Image starten
Starten Sie das Image im Vordergrund (ohne -d
). Es sollte "Hallo Welt" ausgeben.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Starten Sie das Image mit folgendem Befehl:
docker run demo01
2.3: Image mit Argumenten starten
Starten Sie das Image, sodass es "Hallo <name>" ausgibt, wobei <name>
Ihr Name sein sollte.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Starten Sie das Image mit folgendem Befehl:
docker run demo01 <name>
Aufgabe 3 - Vorbereitung einer kleinen Webapp
3.1: app.py anlegen
Erstellen Sie im Ordner /home/coder/workspace/mein-erstes-image
eine Datei app.py
mit folgendem Inhalt:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Web App with Python Flask!'
app.run(host='0.0.0.0', port=80)
Diese Pythondatei definiert und startet eine kleine Flask-Webanwendung. Die Anwendung ist über Port 80 erreichbar.
3.2: requirements.txt anlegen
Erstellen Sie im Ordner /home/coder/workspace/mein-erstes-image
eine Datei requirements.txt
mit dem Inhalt:
Flask>2<3
Ihr Ordner sollte nun wie folgt aussehen:
├── app.py
├── Dockerfile
└── requirements.txt
0 directories, 3 files
Aufgabe 4 - Dockerfile für die Webapp erweitern
4.1: Python installieren
Installieren sie mit Hilfe von apt-get
die Pakete python3
und python3-pip
.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Ihr Dockerfile sollte nun wie folgt aussehen:
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ && rm -rf /var/lib/apt/lists/*
Zunächst wird der Paketmanager auf den neuesten Stand gebracht. Anschließend sollen die Pakete installiert werden. Dieser Teil des Befehls ist essenziell. Der Update- und der rm-Befehl ist Best Practice und wird im nachfolgenden Kapitel genauer behandelt. Die Option -y gibt dabei mit, dass auf die Installationsfrage automatisch yes
geantwortet wird. Zuletzt sollten wir den Paket-Cache löschen, um das Image klein zu halten.
4.2: Abhängigkeiten installieren
- Erweitern Sie Ihr Dockerfile, sodass die Datei
requirements.txt
in das Image in den Ordner/app
kopiert wird. Nutzen Sie denWORKDIR
-Befehl, um in den Kontext /app zu wechseln. - Installieren Sie die Abhängigkeiten mit folgendem Befehl:
python3 -m pip install -r requirements.txt
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Ihr Dockerfile sollte nun wie folgt oder ähnlich aussehen:
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . RUN python3 -m pip install -r requirements.txt
4.3: Webapp einbinden und starten
- Kopieren Sie die Datei
app.py
in das Image. - Dokumentieren Sie Port 80 als Zugang zur Anwendung.
- Führen Sie
python3 app.py
beim Start des Images aus.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Ihr Dockerfile sollte nun wie folgt aussehen:
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . RUN python3 -m pip install -r requirements.txt COPY app.py . EXPOSE 80 CMD ["python3", "app.py"]
4.4: Image bauen und testen
- Bauen Sie das Image mit dem neuen Dockerfile.
- Starten Sie das Image mit einer Portweiterleitung, sodass Sie die Webapp über den Browser erreichen.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Führen Sie zum Bauen folgenden Befehl aus:
docker build -t demo01 .
- Starten Sie das Image wie folgt:
docker run -p 8080:80 demo01
- Versuchen Sie die Webapp in einem neuen Tab unter
http://code-0.labs.corewire.de:8080/
zu öffnen. - Wichtig:
http
nichthttps
code-0
durch Ihre Instanz ersetzen.
- Bei Erfolg können Sie wieder zur VSCode Instanz wechseln und den Container mit
Strg+C
beenden.
Aufgabe 5 - User im Container ändern
5.1: Nicht-Root Benutzer anlegen
Aus Sicherheitsgründen wollen wir die Webapp im Container nun mit einem Benutzer ausführen, der keine Root-Rechte besitzt. Dafür müssen wir einen Benutzer anlegen. Das geht mit folgendem Befehl:
groupadd --system --gid 10100 app-runner-group \
&& useradd --system --gid 10100 --uid 10100 app-runner-user
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Ihr Dockerfile sollte nun wie folgt aussehen:
[...] RUN python3 -m pip install -r requirements.txt RUN groupadd --system --gid 10100 app-runner-group \ && useradd --system --gid 10100 --uid 10100 app-runner-user COPY app.py . [...]
5.2: Nicht-Root Benutzer verwenden
Stellen Sie nun sicher, dass die Webapp mit dem angelegten Nutzer app-runner-user
ausgeführt wird.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Ihr Dockerfile sollte nun wie folgt aussehen:
[...] RUN groupadd --system --gid 10100 app-runner-group \ && useradd --system --gid 10100 --uid 10100 app-runner-user USER app-runner-user COPY app.py . [...]
5.3: Image bauen und testen
- Bauen Sie das Image mit dem neuen Dockerfile.
- Starten Sie das Image mit einer Portweiterleitung, sodass Sie die Webapp über den Browser erreichen.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Führen Sie zum Bauen folgenden Befehl aus:
docker build -t demo01 .
- Starten Sie das Image wie folgt:
docker run -p 8080:80 demo01
- Versuchen Sie die Webapp in einem neuen Tab unter
http://code-0.labs.corewire.de:8080/
zu öffnen. - Wichtig:
http
nichthttps
code-0
durch Ihre Instanz ersetzen.
- Bei Erfolg können Sie wieder zur VSCode Instanz wechseln und den Container mit
Strg+C
beenden.
Privilegierte Ports (Ports < 1024) ohne Root-Rechte
Seit Docker 20.10.0 (Release: 08.12.2020, Release notes) können Container auch Ports < 1024 verwenden ohne Root-Rechte zu benötigen.
Eine alternative Lösung für ältere Versionen, den Container ohne Root-Rechte
laufen zu lassen wäre, in der app.py
Port 80 durch zum Beispiel Port 8080
zu ersetzen und die Portweiterleitung bei docker run
entsprechend anzupassen.
Sie haben nun erfolgreich eine bestehende Anwendung containerisiert. Im Dockerfile haben Sie alles definiert, was notwendig ist damit die Anwendung ohne Fehler ihren Zweck erfüllen kann.