Deploye dein Modell in den OpenStack

Download this notebook

Vorbereitungen

Bevor du den OpenStack der Universität Münster nutzen kannst, musst du die Nutzung über ein Antragsformular bei der WWU Cloud beantragen. Das Formular findest du hier. Falls du dir unsicher bist, welche Ressoucren du benötigst und in den Antrag schreiben sollst, melde dich gerne bei uns. Wir helfen dir gerne bei der Einschätzung.

Falls du deinen Webservice über eine Domain (Uni-extern) erreichbar machen möchtest, solltest du ebenso eine Floating-IP “Externe erreichbare feste IP-Adressen, ggf. mit Eintrag im NIC” beantragen (mehr zur Einrichtung weiter unten).

Bitte beachte, dass die Bearbeitung deines Antrags im CIT ggf. ein paar Tage dauern kann.

Erste Schritte mit dem OpenStack

Wenn dein Antrag bearbeitet wurde, kannst du dich unter https://openstack.wwu.de im OpenStack mit deiner WWU-Kennung und deinem Passwort einloggen. Dich empfängt dann eine Dashboard-Übersicht, ähnlich zu dieser:

alt-text

Auf der linken Seite findest du das Menü, über das du auf die verschiedenen Ebenen des OpenStack zugreifen kannst. Die wichtigsten Punkte für die alltägliche Nutzung werden für uns “Instanzen”, “Datenträger” und “Netzwerk” sein. Auf diese werden wir im Folgenden insbesondere eingehen. Als Nächstes beginnen wir, die Einrichtung einer Virtuellen Maschine (VM) vorzunehmen.

Einrichtung deiner ersten VM

Um eine VM starten zu können, benötigt sie (ganz wie ein echter PC) einen Datenträger, also eine Art Festplatte. Zusätzlich musst du bereits bei der Einrichtung deinen SSH-Key hinterlegen, um nach dem Start per SSH auf die Maschine zugreifen zu können.

Hinterlegen deines SSH-Keys

Klicke im Menü auf Compute -> Schlüsselpaare. Hier werden dir deine bereits hinterlegten SSH-Keys angezeigt. Falls du den OpenStack zum ersten Mal nutzt, kannst du nun einen neuen Schlüssel hochladen. Wie du einen SSH-Key auf deinem Rechner erstellst, erfährst du im Kapitel Verwalte deinen Code mit GitLab. Du kannst denselben SSH-Schlüssel nutzen, den du auch dort generiert hast, aus Sicherheitsgründen empfehlen wir allerdings, einen neuen Schlüssel für den OpenStack zu verwenden.

Hast du einen Schlüssel auf deinem Rechner, klicke nun auf “Öffentlichen Schlüssel importieren”. Du kannst dem Schlüsselpaar nun einen Namen geben (zum Beispiel den Namen deines Rechners, wenn du mit mehreren Rechnern arbeitest). Wähle als Schlüsseltyp SSH-Schlüssel und lade die Datei des Öffentlichen Schlüssels. In der Regel findest du diese auf deinem Rechner im Home-Verzeichnis unter

~/.ssh/[schlüsselname].pub

WARNUNG: Gib niemals die private Schlüsseldatei heraus oder lade sie irgendwo hoch. Die Authentifizierung erfolgt ausschließlich durch Weitergabe des Public-Keys.

Dieses Schlüsselpaar kannst du später bei der Erstellung der VM angeben, um dich initial per SSH mit dem System verbinden zu können.

Erstellen eines Datenträgers

Um einen Datenträger für eine VM zu erstellen, klicke nun auf Datenträger → Datenträger und anschließend oben rechts auf Datenträger erstellen.

alt-text

Gib dem Volume nun einen Namen. Hier empfiehlt sich, den Namen zu nehmen, der später auch der VM zugeordnet wird, um die Zuordnung einfacher zu halten. In unserem Beispiel nennen wir das Volume “price-api”.

Wähle als Datenträger Quelle den Punkt Abbild aus. Nun kannst du ein bereits vorgefertigtes Image nutzen, hier gibt es eine ganze Menge zur Auswahl, insbesondere was verschiedene Linux-Systeme angeht. Wähle das System, das für dich am besten passt. Wir wählen in unserem Beispiel Ubuntu 22.04.

Der Typ replicated_bronze ist für uns erst einmal gut, die anderen Typen sind eher dafür geeignet, Datenbanken zu hosten.

Gib nun eine Größe an. Hier hast du theoretisch freie Wahl, dennoch solltest du beachten, dass du große Datenmengen wie Trainingsdaten besser auf einem usershare ablegen kannst (den du später natürlich auch in deine VM integrieren kannst). Deshalb empfehlen wir, auf dem System-Volume nur deinen Code sowie weitere Software abzulegen, aber keine großen Datensätze oder Ähnliches. Mit ein bisschen Luft nach oben wählen wir als Volume-Größe 48GB.

Die Verfügbarkeitszone und die Gruppe sind für uns nicht relevant.

Klicke zum Erstellen des Volumes auf Datenträger erstellen.

Erstellen der Sicherheitsgruppen

Aus Sicherheitsgründen ist bei allen VMs im OpenStack erst einmal die Firewall für alle Ports aktiv, d.h. es darf kein Netzwerkverkehr in die VM hereingehen. Du musst für jeglichen Traffic in die Maschine angeben, von wo aus er kommt und welche Kommunikation (Protokoll/Port) aufgenommen werden darf.

Da wir uns zunächst per SSH mit der VM verbinden möchten, müssen wir also eine Sicherheitsgruppe für den SSH-Verkehr einrichten. Klicke dazu auf Netzwerk → Sicherheitsgruppen und dann auf Sicherheitsgruppe erstellen. Gib der Sicherheitsgruppe einen Namen. Wir empfehlen, diese einfach “SSH” zu nennen und dort alle Regeln zu definieren, die für den SSH-Verkehr notwendig sind.

Nun möchten wir erlauben, dass wir von unserem Computer aus Kontakt mit der VM aufnehmen dürfen. Dies geht zunächst nur über das WWU-Netz. Du musst also entweder mit dem LAN/WLAN der Uni oder per VPN verbunden sein. Eine Anleitung, wie du eine VPN-Verbindung ins Uni-Netz aufbaust, findest du hier.

Nun klickst du auf Regel hinzufügen. Im erscheinenden Dialog wählst du als Regeltyp den letzten Punkt SSH aus. Als Beschreibung kannst du beispielsweise den Namen deines Computers angeben. Falls du mit mehreren Computern arbeitest, kannst du diese so besser identifizieren. Belasse den Punkt Entfernt bei der Auswahl CIDR.

Hier kannst du nun entweder eine einzelne IP oder aber ganze IP-Blöcke angeben, von denen eine SSH-Verbindung erlaubt wird. Merke dabei: Je spezifischer die IP angegeben wird, desto sicherer. Da im Uni-Netz in der Regel feste IP-Adressen vergeben werden, geben wir hier unsere genaue IP an.

Innerhalb des Uni-LAN Netzes sollte deine IP-Adresse mit 128.176… beginnen, innerhalb des Uni WLANs oder bei VPN-Verbindung sollte diese mit 10.67… (WLAN) bzw. 10.68… (VPN) beginnen. Du kannst die IP herausfinden, indem du in der Kommandozeile (Windows) ipconfig eingibst, bei macOS bzw. Linux kannst du ifconfig eingeben. Falls dies nicht hilft, kannst du auf dem jeweiligen System auch in die Systemeinstellungen zum Netzwerk gehen.

Gib nun im Feld CIDR deine IP-Adresse ein und am Ende den Postfix /32.

Der Postfix /32 gibt an, dass alle 32 Bits der IP-Adresse genutzt werden, also nur genau diese IP eine Verbindung zur VM aufbauen darf. Beispielsweise dürfte mit der Eingabe 192.168.0.0/16 jede IP eine Verbindung aufbauen, die mit 192.168… beginnt.

Wenn du alle Uni-Münster-Adressen erlauben möchtest, gib 10.68.0.0/16 und 10.67.0.0/16, sowie 128.176.0.0/16 an.

Klicke abschließend auf Hinzufügen und wiederhole den Vorgang ggf. für weitere IP-Adressen, die von der Firewall freigegeben werden sollen.

TODO: ERKLÄRE FLOATING IPs HIER

Erstelle deine Instanz

Details

Gehe nun im Menü Compute -> Instanzen und klicke oben rechts auf Instanz starten. Dort kannst du deiner Instanz einen sinnvollen Namen geben und eine Beschreibung hinzufügen. Die anderen Felder lassen wir wie vorausgefüllt (Verfügbarkeitszone AvailabilityZone1 und Anzahl 1). Klicke nun auf Weiter.

alt-text

Quelle

Wähle nun ein verfügbares, bootbares Volume aus (z.B. das zuvor erstellte) und klicke auf den Pfeil nach oben, sodass es zugewiesen wird. Dann kannst du auf Weiter klicken.

alt-text

Variante

Im nächsten Schritt müssen wir eine Variante auswählen. Gehe dabei nach dem Grundsatz “So groß wie nötig, so klein wie möglich” vor. Wir nutzen die Variante small, da wir das TensorFlow-Tutorial hier laufen lassen wollen und dies hoffentlich genügt.

TODO: KANN DAS SPÄTER SKALIERT WERDEN?

Netzwerke und Netzwerk Ports

Hier kann alles bleiben wie voreingestellt.

Sicherheitsgruppen

Gehe hier wie zuvor bei den Instanzen vor und füge die erstellte Sicherheitsgruppe hinzu.

Da wir eine Web-App hosten wollen, fügen wir die Sicherheitsgruppen HTTP und SSH ebenfalls hinzu, um die entsprechenden Ports innerhalb des Uni-Netzes zu öffnen.

alt-text

Key-Pair

Hier können weitere SSH-Keys, z.B. von weiteren Endgeräten, hinzugefügt werden. Achte dabei auf jeden Fall darauf, dass dein eigener Key hinzugefügt ist.

Wenn du weiteren Kolleg*innen den Zugriff per SSH ermöglichen möchtest, musst du auch deren öffentliche Schlüssel in obigen Schritt Key-Pair hinzufügen. Dies kann auch nachträglich per SSH erfolgen.

Konfiguration

Hier können wir weitere fortgeschrittene Einstellungen vornehmen, die beim Start der Instanz ausgeführt werden. Wir werden dies jedoch auf der Instanz später manuell nachholen, sodass wir den Schritt überspringen.

Servergruppen, Schedulerhinweise und Metadaten

Diese Schritte können ebenfalls einfach übersprungen werden.

Instanz starten

Klicke anschließend auf Instanz starten. Die Instanz wird nun gestartet und nach einigen Sekunden in der Liste angezeigt. Warte, bis dort der Zustand auf Läuft wechselt. Deine Konfiguration kannst du dir durch Klicken auf den Instanznamen anzeigen lassen. Kopiere dir zudem die IP-Adresse der Instanz.

Verbinde dich mit der Instanz

Nun kannst du dich mit der Instanz per SSH verbinden. Öffne dazu lokal ein Terminal und verbinde dich mit dem Server mit dem Kommando

ssh ubuntu@xxx.xxx.xxx.xxx,

wobei die vorher kopierte IP-Adresse (IPv4) zu nutzen ist. Solltest du zuvor ein anderes Image als ubuntu gewählt haben, ist der Username anders. Wenn alles funktioniert hat, solltest du das folgende Fenster sehen. Dies ist ein Linux-Computer, der wie übliche Linux-Rechner funktioniert, leider nur ohne Benutzeroberfläche.

alt-text

Weiteren User anlegen

Bislang hast du nur einen root user. Es ist zwingend notwendig, einen weiteren User anzulegen.

sudo adduser username

Der Username muss nicht mit einer Person übereinstimmen, er kann zum Beispiel einfach der Name deines Projektes sein. Du wirst nach einem Passwort gefragt. Gib ein selbst generiertes Passwort ein und speichere dieses unbedingt.

alt-text

Den Usern sudo Rechte geben

Wir benötigen sudo Rechte für den User, damit dieser z.B. Docker ausführen kann. Dies kannst du als root User mit folgendem Kommando machen:

sudo usermod -aG sudo username

Weitere SSH Schlüssel hinzufügen

Wir melden uns als superuser an mit root Rechten an: sudo su. Es wird nach einem Passwort gefragt, der User hat aber kein Passwort! Drücke einfach Enter und gehe in die Directory cd /home/username. Lege dort den Ordner mkdir .ssh an und gehe in diesen Ordner cd /.ssh. Lege nun eine Datei authorized_keys an mit dem Kommando touch authorized_keys.

Nun kommen wir zu dem sehr handlichen Editor vim. Mit dem Kommando vi authorized_keys kommst du in die Datei. Die Nutzung von vim ist etwas gewöhnungsbedürftig. Drücke die Taste i (Insert-Modus), um etwas einzufügen. Füge dann einfach den kopierten Public-Key komplett ein (diesen erhältst du auf DEINER Maschine z.B. durch das Kommando cat ~/.ssh/id_rsa.pub [die Taste für ~ ist auf Windows Tastaturen “alt gr” + “+”, auf macOS mit option + N]). Solltest du Windows nutzen, suche am besten den versteckten Ordner C:\Users\<windows-nutzername>\.ssh, öffne die Datei id_rsa.pub (oder ähnlich) mit dem Editor (!), und kopiere den Inhalt. Durch Drücken der Taste ESC schließt du den Insert-Modus wieder und kannst mit dem Kommando :wq die Datei speichern (write) und schließen (quit).

Du kannst so auch weitere Keys als neue Zeilen hinzufügen.

Achtung: Tippe nun exit ein, um nicht mehr als super user zu agieren.

Tippe nochmal exit ein, um dich aus der Instanz auszuloggen.

Teste nun den neuen User mit

ssh username@ip-adress

Du müsstest jetzt als dieser User auf der Maschine angemeldet sein.

Üblicherweise solltest du diesen User nutzen, die root Rechte benötigen wir im Folgenden nicht mehr.

alt-text

Update deine Instanz

Wir nutzen nun den neu angelegten User anstatt des ursprünglichen Users. Zunächst updaten wir noch unsere Instanz mit folgendem Kommando:

sudo apt update
sudo apt upgrade

Hier musst du ein Passwort angeben. Dieses ist das vorhin mit dem user angelegte Passwort. Bestätige das Upgrade mit Y. Dies kann ein wenig dauern.

TODO: WARUM FUNKTIONIERT DAS AUF WINDOWS NUR PER COMMAND PROMPT IN VS CODE?

Ggf. erscheint ein Fenster, in dem du noch etwas auswählen kannst. Gehe mit der Taste TAB auf OK und drücke jeweils Enter.

alt-text

Am Ende muss die Instanz neu gestartet werden, nutze dafür

sudo reboot now

Dann wirst du direkt rausgeschmissen und kannst ggf. auf der Weboberfläche des OpenStack sehen, dass etwas geschieht. Du kannst dich dann wieder einloggen.

Deploye deinen Docker-Container

Installiere Docker

Verbinde dich wieder mit dem User per SSH auf die Instanz. Üblicherweise updaten wir nochmal die Liste der Pakete:

sudo apt update

und installieren danach mithilfe von

sudo apt install apt-transport-https ca-certificates curl software-properties-common apache2-utils

notwendige Pakete. Bestätige ggf. mit Y. Nun muss der GPG-Key zum verifizieren der Gültigkeit des Docker Pakets hinzugefügt werden:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Füge dann das Docker-Repository hinzu:

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu jammy stable"

und bestätige nochmal.

ACHTUNG: jammy ist die aktuell genutzte Ubuntu Version 22.04, ggf. muss der Codename angepasst werden.

Mit apt-cache policy docker-ce können wir checken, welche Version von Docker installiert werden würde:

incubai@incubai-tutorial:~$ apt-cache policy docker-ce
docker-ce:
  Installed: (none)
  Candidate: 5:24.0.7-1~ubuntu.22.04~jammy

Wir installieren nun Docker mit

sudo apt install docker-ce

und es sollte installiert werden. Mit dem Kommando

sudo systemctl status docker

sehen wir den Status, du siehst irgendwann:

docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2024-01-17 15:11:51 UTC; 14s ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 3692 (dockerd)
      Tasks: 7
     Memory: 26.8M
        CPU: 324ms
     CGroup: /system.slice/docker.service
             └─3692 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Mit :q kannst du den Output wieder verlassen. Der Output zeigt, dass Docker läuft, sich beim Systemstart mit startet (enabled).

Docker muss mit sudo Rechten ausgeführt werden. Du kannst dies automatisieren, indem du einen docker user erstellst

sudo usermod -aG docker ${USER}

und

su - ${USER}

eingibst (${USER} gibt automatisiert den Nutzernamen zurück, probiere z.B. echo ${user}). Hier benötigst du wieder das Passwort deines Nutzers. Überprüfe dies mit dem Kommando groups und füge deinen User dieser Gruppe hinzu:

sudo usermod -aG docker <username>

Nun müssten Docker-Kommandos ohne sudo ausführbar sein.

Pulle den Container

TODO: Container ins GitLab hinzufügen?

Nun muss der im Gitlab (oder Harbor) liegende Container geladen werden (siehe auch Kapitel 3.1) LINK Falls du den Container noch nicht in eine Registry gepusht hast, gehe nochmal zum Ende des Kapitels.

Wie schon zuvor beim pushen muss nun der Zugriff auf das Container-Repository durch den Server möglich sein. Dazu können wir uns per Docker mit unserem Username des Registry-Users (im Falle der Uni Münster, die Nutzerkennung) einloggen (siehe auch 3.1).

docker login <registry url> -u <username> -p <token>

Für das Zivgitlab wäre das der folgende Befehl docker login zivgitlab.wwu.io -u <uni nutzerkennung> -p <token>.

Jetzt sind wir endlich so weit und können den Container pullen.

docker pull <registry url>/<namespace>/<project>/<container-name>

in diesem Fall wäre es die URL, die du in Kapitel 3.1 erhältst. (hier reach-euregio/incubaitor/openstack-tutorial).

Nun kann der Container gestartet werden. Da unser Container auf dem Port 5000 läuft, müssen wir diesen auf 80 (HTTP) mit dem Zusatz -p <maschinen port>:<container port> routen:

docker run -p 80:5000 zivgitlab.wwu.io/reach-euregio/incubaitor/openstack-tutorial

Teste auch den folgenden Link, der nun für Zugriffe innerhalb des Universitätsnetzes zugänglich ist:

http://<ip-adresse>/api/car-price?model=T-Roc&year=2019&transmission=manual&mileage=12123&fuelType=petrol&tax=145&mpg=42.7&engineSize=2.0

TODO: NEUSTART etc. ERKLÄREN

  • Floating IP
  • Traefic/Reverse Proxy/Lets Encrypt
  • Portainer (muss nicht unbedingt)

Floating IP

Wird die Webanwendung neu gestartet, so erhält diese von OpenStack meistens eine neue, ggf. andere IP-Adresse. Zudem ist die IP-Adresse nicht von außen erreichbar. Deshalb hatten wir beim OpenStack Projektantrag (siehe oben) zunächst auch eine Floating-IP mit beantragt.

Du findest deine Floating-IP im OpenStack Dashboard über Netzwerk > Floating-IPs. Diese kannst du dann über den Button Zuweisen zuweisen. Über Protokoll wird verknüpft müsstest du nun deine zuvor erstellte Instanz mit der internen IP-Adresse finden.

TODO: Screenshot Floating IP hinzufügen

Im obigen Link kannst du nun die Floating-IP statt der internen IP-Adresse angeben:

http://<floating-ip-adresse>/api/car-price?model=T-Roc&year=2019&transmission=manual&mileage=12123&fuelType=petrol&tax=145&mpg=42.7&engineSize=2.0

Diese ist nun im Uni-Netz statisch erreichbar. Falls diese auch extern erreichbar sein soll, müsstest du das NIC kontaktieren. Diesen Schritt solltest du aber nur machen, falls du wirklich ein System nach außen öffnen möchtest. Kontaktiere uns gerne, falls du mehr dazu wissen möchtest.

Generell kannst du aber auch bei deinem Domain-Service nun den A-Record auf diese Floating-IP setzen, und über die Domain kann die Anwendung dennoch innerhalb des Uni-Netzes erreicht werden! Mehr zu IP-Adressen und Hosting findest du z.B. hier.

SSL-Zertifikat und Reverse Proxy

Wir haben nun eine laufende (extern erreichbare) Domain mit unserer Anwendung. Wir erhalten jedoch Warnmeldungen im Browser, da wir keine HTTPS Verbindung eingerichtet haben und kein gültiges SSL-Zertifikat haben.

Zudem kann auf unserer Instanz nun leider nur diese eine Anwendung erreicht werden, da diese die Standard Ports für HTTP 80 (und HTTPS 443) blockiert. Falls wir noch weitere Anwendungen auf der Instanz laufen lassen wollen, müssen wir einen Reverse Proxy einrichten.

Solltest du nur diese eine Anwendung laufen lassen wollen, kannst du dir auch ein Zertifikat über deinen Domain-Service (teuer) oder den Lets-Encrypt Certbot beschaffen und einrichten. Dies ist allerdings ähnlich kompliziert wie die Einrichtung von Traefik, die wir nun vorschlagen. Es gibt auch Alternative Reverse Proxies (z.B. von nginx), die Einrichtung ist aber ebenfalls komplizierter als über Traefik.

Traefik Konfiguration

Im Git findest du im Ordner traefik eine Datei docker-compose.yaml (zu Docker-Compose findest du mehr im Kapitel Docker).

Hier wird zunächst die Docker-Compose Version angegeben. Danach folgen die Services, in denen wir mehrere Container konfigurieren und starten können. Hier wird das Image traefik in der Version v2.11 genutzt (siehe besser davon ab, den Tag latest zu nutzen, um keine ungewollten Probleme zu bekommen). Du findest verschiedene Versionen auf Docker-Hub. Beachte dabei ggf. auch die Rate-Limits des Docker-Hubs (siehe Kapitel 4.1) und nutze stattdessen den Proxy des Harbor.

version: "3.8"
services:
  traefik: 
    image: "traefik:v2.11"
    container_name: traefik
    restart: unless-stopped

Zudem geben wir dem Container einen Namen und spezifizieren, dass dieser Container immer neu gestartet wird, falls er mal abraucht (oder der gesamte OpenStack).

In der weiteren Konfiguration

    security_opt:
      - "no-new-privileges:true"
    networks:
      - proxy
    ports:
      - "80:80"
      - "443:443"

routen wir die Ports 80 und 443 des Traefik Containers nach außen.

Nun müssen wir einige Files vom System im Container verfügbar machen (mounten).

    volumes:
      - "/etc/localtime:/etc/localtime:ro"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik-data/traefik.yml:/traefik.yml:ro"
      - "./traefik-data/acme.json:/acme.json"
      - "./traefik-data/configurations:/configurations"

Der Container nutzt

  • /etc/localtime vom System als Read-Only (:ro) um die Zeitkonfiguration des Servers zu übernehmen.
  • /var/run/docker.sock ist der Docker-Socket des Systems, welches wir zuvor installiert hatten, worüber Traefik den Status der Container auf dem Server sehen kann.
  • Danach kommen drei Konfigurationsfiles, die wir weiter unten noch erstellen werden.

Über die folgenden Labels konfigurieren wir Traefik als ersten Service auf unserer Instanz.

    labels:
      - traefik.enable=true
      - traefik.docker.network=proxy
      - traefik.http.routers.traefik-secure.entrypoints=websecure
      - traefik.http.routers.traefik-secure.rule=Host(`traefik.<meine-domain.tld>`)
      - traefik.http.routers.traefik-secure.service=api@internal
      - traefik.http.routers.traefik-secure.middlewares=user-auth@file

Hinweis: Denke daran, deine Domain anzupassen!

TODO: EXPLAIN

Am Ende des Docker-Compose Files geben wir das interne Docker-Netzwerk (welches wir proxy nennen) frei, sodass andere Container mit diesem kommunizieren können:

networks:
  proxy:
    external: true

Das Netzwerk erstellen wir gleich mit dem Command docker network create proxy auf unserer Instanz. Über docker network ls kannst du alle Netzwerke des Docker-Services auf der Instanz einsehen (siehe unten).

Hinweis: Hier musst du dich wieder per SSH einloggen, wobei du nun die neue Floating-IP nutzen musst.

Den File acme.json legen wir nur an, dieser wird später automatisch befüllt. Im Konfigurationsfile traefik.yml werden die wichtigsten Einstellungen von Traefik vorgenommen und Lets Encrypt für das SSL Zertifikat konfiguriert. Ändere hier die Mail-Adresse!

Weiterhin haben wir eine Konfigurationsdatei /configurations/dynamic.yml, wo wir nun einen Username und ein Password gehasht eingeben müssen. Dieser Username und das Passwort ist für den Login im Traefik Dashboard und du kannst sie frei wählen. Mir dem folgenden Kommando kannst du die Zeile für users erzeugen:

echo $(htpasswd -nb <username> <password>)

Auf unserer Demo Instanz kannst du dich mit incubai und dem Passwort demo einloggen. Dann ist die Zeile in der Konfiguration z.B. incubai:$apr1$f6Zt/4cW$XRwvPtS.f9OeGSffJ6pOF1

Nun sind wir fertig mit der Konfiguration und müssen die Daten noch auf den Server laden. Dies können wir mit SSH (von unserer lokalen Kommandozeile aus!) machen:

scp -r ./traefik <username>@<floating-ip>:/home/<username>/.

Nun können wir wieder per SSH auf den Server gehen und checken, ob die Dateien richtig abgelegt wurden. Mit dem Editor vi kannst du ggf. noch Änderungen vornehmen.

Nun können wir den bereits laufenden Container mit docker stop <container_id> stoppen. Die Container ID findest du mit docker container ls, wobei du die ID als Hash findest, aber auch den fantasievollen Namen nutzen kannst (wir hätten dem Container beim Start auch einen Namen geben können --name incubai-tutorial).

Nun starten wir den neuen Service mit docker compose up (wir müssen hierzu im Ordner mit dem docker-compose.yaml sein!). Dann wird der neue Service gebaut und installiert. Hierbei kann es zu Fehlern kommen, daher schaue dir den Output genau an. In unserem Fall

traefik  | time="2024-01-31T14:45:34Z" level=error msg="The ACME resolver \"letsencrypt\" is skipped from the resolvers list because: unable to get ACME account: permissions 664 for acme.json are too open, please use 600"

waren die Rechte für den File acme.json falsch, sodass wir den Container mit CTRL-C wieder stoppen. Wir legen die Rechte für die Datei mit

chmod 600 ./traefik-data/acme.json

Nun können wir es nochmal mit Docker Compose versuchen. Dafür sollte der A-Record von deiner Domain/Subdomain gesetzt sein!

Solltest du keine von außen erreichbare IP haben, kommt es beim Zertifikat noch zu Fehlern, da Lets Encrypt unseren Server nicht erreichen kann. Dies hindert uns aber nicht daran, den Service über traefik.<meine-domain.tld> zu erreichen. Wir erhalten dann aber eine Warnung, dass die Seite unsicher ist. Unsere Instanz kannst du mit den oben angegebenen Nutzerdaten hier (nur aus dem Uni-Netz) einsehen.

Als Nächstes müssen wir unseren Docker-Container für Traefik an den Start bringen.

Dazu legen wir einen neuen Ordner demo an, sowie darin ein neues docker-compose.yaml-File an. Unter services wählen wir in dieser Demo den Namen carprice-api, der das Docker-Image zivgitlab.wwu.io/reach-euregio/incubaitor/openstack-tutorial:latest benutzt sowie den Namen carprice bekommt.

version: "3.8"
services:
  carprice-api: 
    image: "zivgitlab.wwu.io/reach-euregio/incubaitor/openstack-tutorial:latest"
    container_name: carprice
    restart: unless-stopped

Statt die Ports manuell freizugeben, öffnen wir den von unserer Anwendung genutzten internen Port 5000.

security_opt:
      - "no-new-privileges:true"
    networks:
      - proxy
    expose:
      - 5000

Wir benötigen keine Volumes für unsere App, die labels für traefik passen wir folgendermaßen an:

labels:
      - traefik.enable=true
      - traefik.docker.network=proxy
      - traefik.http.routers.carprice-api.entrypoints=websecure
      - traefik.http.routers.carprice-api.rule=Host(`demo.<meine-domain.tld>`)
      - traefik.http.routers.carprice-api.service=carprice-api-demo

Hier müssen wir zunächst das label .traefik-secure durch den Namen unseres Services carprice-api sowie die Domain durch unsere gewünschte Domain (demo.<meine-domain.tld>) ersetzen . Der Service wird auf carprice-api-demo gesetzt, wobei carprice-api der Name unseres Services ist und demo der Name des Ordners, in dem wir unseren Service starten. Außerdem können wir die middleware löschen, da wir keinen Login vorsehen.

Zu guter Letzt geben wir wieder das Netzwerk an.

networks:
  proxy:
    external: true