# Jetzt alles online bringen In diesem Kapitel zeige ich, wie so ein Projekt online gestellt werden kann. Der Server für dieses Projekt wird von Hetzner bereitgestellt, es ist aber natürlich auch auf jedem anderen Server möglich. Hier ist nur die Kurzanleitung. Für die Serverkonfiguration, Docker, etc. gibt es viele gute Tutorials im Internet. Das würde hier den Rahmen sprengen. ## Server Als Server dient uns ein Hetzner Cloud Server auf dem ich mehrere Projekte hoste. Dieser Server ist ein virtueller Server, der in einem Rechenzentrum von Hetzner betrieben wird. Der Server ist über das Internet erreichbar und kann für verschiedene Anwendungen genutzt werden. Die Spezifikationen des Servers sind: - 4 vCPUs (ARM) - 8 GB RAM - 40 GB SSD - Aktuelle Kosten ca. 7€/Monat - Debian 6 Über die Hetzner Cloud Console kann der Server verwaltet werden. Hier können wir den Server starten, stoppen, neustarten, die IP-Adresse einsehen und vieles mehr. Zuerst empfehle ich das anlegen eines SSH-Keys, um sich sicherer mit dem Server zu verbinden. (https://community.hetzner.com/tutorials/howto-ssh-key/de) Dann verbinde ich mich über die terminal.app im Mac mit meinem Server: ```sh ssh root@deine_server_ip ``` Update und Upgrade deines Systems: ```sh apt-get update apt-get upgrade -y ``` ## Docker Installiere benötigte Pakete: ```sh apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common -y ``` Füge den Docker GPG-Schlüssel hinzu: ```sh curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - ``` Füge das Docker-Repository hinzu: ```sh echo "deb [arch=arm64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list ``` Update die Paketliste: ```sh apt-get update ``` Installiere Docker: ```sh apt-get install docker-ce -y ``` Überprüfe die Docker Installation: ```sh docker --version ``` Als Antwort solltest ihr so etwas sehen: ```sh root@debian-4gb-nbg1-1:~# docker --version Docker version 20.10.24+dfsg1, build 297e128 ``` Lade Docker Compose für ARM herunter: ```sh curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose ``` Setze die Berechtigungen: ```sh chmod +x /usr/local/bin/docker-compose ``` Überprüfe die Docker Compose Installation: ```sh docker-compose --version ``` Als Antwort solltest ihr so etwas sehen: ```sh root@debian-4gb-nbg1-1:~# docker-compose --version docker-compose version 1.29.2, build unknown ``` ## Portainer (optional) Portainer ist ein Open-Source-Tool zur Verwaltung von Docker-Containern. Es bietet eine grafische Benutzeroberfläche, mit der Benutzer Container, Images, Netzwerke und Volumes verwalten können. Portainer ist nicht notwendig, kann aber die Verwaltung von Docker-Containern erleichtern. Erstelle ein neues Docker-Volume für Portainer: ```sh docker volume create portainer_data ``` Starte den Portainer-Container für ARM: ```sh docker run -d -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:linux-arm ``` Bei mir sind schon einige Container installiert, bei dir sollte Portainer der einzige Container sein. Öffne Portainer in deinem Browser: ```sh http://deine_server_ip:9000 ``` ![portainer.png](portainer.png) ## Streamlit Wie bekomme ich jetzt die Streamlit Anwendung auf den Server? Wir erstellen ein Docker-Image mit unserer Streamlitanwendung und laden dieses auf den Server. Dort starten wir dann den Container. Zuerst ein Dockerfile erstellen im Anwendungsverzeichnis erstellen: ```sh nano Dockerfile ``` Füge folgenden Inhalt ein: ```sh FROM python:3.9.6-slim WORKDIR /app RUN apt-get update && apt-get install -y \ build-essential \ curl \ software-properties-common \ git \ && rm -rf /var/lib/apt/lists/* COPY . . RUN pip3 install -r requirements.txt # Expose Port 8501 für Streamlit EXPOSE 8501 # Healthcheck für den Container HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health # Startbefehl für Streamlit ENTRYPOINT ["streamlit", "run", "Home.py", "--server.port=8501", "--server.address=0.0.0.0"] ``` Du kannst natürlich die Python Version und die Portnummer anpassen. Achte auch darauf, dass die Datei zum starten bei mir Home.py heißt. In der requirements.txt Datei stehen alle benötigten Python Pakete. Damit diese mit in dem Docker-Image installiert werden. Die requirements.txt Datei sollte im gleichen Verzeichnis wie das Dockerfile liegen und wird folgendermaßen erstellt: ```sh pip freeze > requirements.txt ``` Deshalb empfehle ich auch immer eine virtuelle Umgebung für jedes Projekt zu erstellen, um später die benötigten Pakete zu installieren und keine Konflikte mit anderen Projekten zu bekommen. Docker Login (Du wirst nach deinem Docker Hub Benutzernamen und Passwort gefragt. Falls nicht vorhanden, auf Docker Hub registrieren): ```sh docker login ``` Nun das Docker-Image erstellen (mit buildx für verschiedene Serverarchitekturen) und mit --push direkt auf Docker Hub hochladen: ```sh docker buildx build -t dein_dockername/dein_imagename --push . --no-cache ``` Dies kann ein paar Minuten dauern. Nun auf dem Server ebenfalls in Docker einloggen: ```sh docker login ``` Das Docker Image ziehen: ```sh docker pull dein_dockername/dein_imagename ``` Mit: ```sh docker images ``` siehst du alle images und kannst die Image ID sehen. Die brauchst du im nächsten Schritt, um den Container zu starten. Nun den Container starten: ```sh docker run -p 8501:8501 -dit --restart unless-stopped ``` Mit ```sh docker ps ``` kannst du nun deinen Container sehen. Deine Anwendung sollte nun unter http://deine_server_ip:8501 erreichbar sein. ## Proxy Manager Jede Streamlit Anwendung wird einem bestimmten Port zugewiesen. Damit wir unserem Server eine Domain (datenflanke.de) zuweisen können und diese dann direkt die richtige Streamlit Anwendung findet, leiten wir jede Anfrage, welche über unsere Domain an den Server gesendet wird, an den richtigen Port weiter. Dafür nutzen wir den Proxy Manager nginx. Verzeichnis erstellen: ```sh mkdir -p /opt/nginx-proxy-manager cd /opt/nginx-proxy-manager ``` Erstelle die Datei docker-compose.yml: ```sh nano docker-compose.yml ``` Füge folgenden Inhalt ein und ersetze root_password und npm_password mit sicheren Passwörtern deiner Wahl: ```sh version: '3' services: app: image: 'jc21/nginx-proxy-manager:latest-armhf' restart: unless-stopped ports: - '80:80' - '81:81' - '443:443' environment: DB_MYSQL_HOST: "db" DB_MYSQL_PORT: 3306 DB_MYSQL_USER: "npm" DB_MYSQL_PASSWORD: "npm_password" DB_MYSQL_NAME: "npm" volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt db: image: 'yobasystems/alpine-mariadb:latest-armhf' restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: 'root_password' MYSQL_DATABASE: 'npm' MYSQL_USER: 'npm' MYSQL_PASSWORD: 'npm_password' volumes: - ./mysql:/var/lib/mysql ``` Starte die Docker-Container: ```sh docker-compose up -d ``` Zugriff auf das Dashboard: ```sh http://deine_server_ip:81 ``` Bei mir sind schon einige Domains hinterlegt. Bei dir sollte die Liste leer sein. ![nginx1.png](nginx1.png) Nun kannst du einen neuen Proxy hinzufügen über Add Proxy Host im Proxy Host Menü: Der Streamlit Standardport ist 8501 - je nach dem welchen Port du beim Start des Dockercontainer benutzt hast. ![proxy1.png](proxy1.png) Wichtig ist hier Custom locations hinzuzufügen, da die Streamlit Anwendung sonst nicht starten kann. (https://discuss.streamlit.io/t/nginx-setup-websocket-connection-error-with-a-subdomain-name/47787) ![proxy2.png](proxy2.png) Und, falls noch nicht geschehen ein SSL Zertifikat hinzufügen: ![proxy3.png](proxy3.png)