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:

ssh root@deine_server_ip

Update und Upgrade deines Systems:

apt-get update
apt-get upgrade -y

Docker

Installiere benötigte Pakete:

apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common -y

Füge den Docker GPG-Schlüssel hinzu:

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

Füge das Docker-Repository hinzu:

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:

apt-get update

Installiere Docker:

apt-get install docker-ce -y

Überprüfe die Docker Installation:

docker --version

Als Antwort solltest ihr so etwas sehen:

root@debian-4gb-nbg1-1:~# docker --version
Docker version 20.10.24+dfsg1, build 297e128

Lade Docker Compose für ARM herunter:

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:

chmod +x /usr/local/bin/docker-compose

Überprüfe die Docker Compose Installation:

docker-compose --version

Als Antwort solltest ihr so etwas sehen:

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:

docker volume create portainer_data

Starte den Portainer-Container für ARM:

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:

http://deine_server_ip:9000

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:

nano Dockerfile

Füge folgenden Inhalt ein:

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:

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):

docker login

Nun das Docker-Image erstellen (mit buildx für verschiedene Serverarchitekturen) und mit –push direkt auf Docker Hub hochladen:

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:

docker login

Das Docker Image ziehen:

docker pull dein_dockername/dein_imagename

Mit:

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:

docker run -p 8501:8501 -dit --restart unless-stopped <imageid>

Mit

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:

mkdir -p /opt/nginx-proxy-manager
cd /opt/nginx-proxy-manager

Erstelle die Datei docker-compose.yml:

nano docker-compose.yml

Füge folgenden Inhalt ein und ersetze root_password und npm_password mit sicheren Passwörtern deiner Wahl:

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:

docker-compose up -d

Zugriff auf das Dashboard:

http://deine_server_ip:81

Bei mir sind schon einige Domains hinterlegt. Bei dir sollte die Liste leer sein. 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

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

Und, falls noch nicht geschehen ein SSL Zertifikat hinzufügen: proxy3.png