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
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.
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.
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)
Und, falls noch nicht geschehen ein SSL Zertifikat hinzufügen: