TL;DR
Streamlit is een geweldig hulpmiddel om vrij eenvoudig prachtige data toepassingen te maken, maar als het aankomt op het implementeren en toegankelijk maken ervan, kan het ingewikkelder zijn voor niet-specialisten. In dit artikel willen we onze reis naar het implementeren van onze applicatie op GCP presenteren, met beperkte toegang voor specifieke mensen. We hebben twee oplossingen geïmplementeerd: één met Cloud Run, de andere met App Engine en we hebben gekozen voor App Engine omdat het zo gemakkelijk is om de applicatie te beveiligen met IAP (Identity-Aware Proxy).

Medium Blog bij Artefact.

Dit artikel werd oorspronkelijk gepubliceerd op Medium.com.
Volg ons op ons medium Blog !

Motivaties voor inzet

In dit artikel nemen we het voorbeeld van de Text Data Explorer, een Streamlit-toepassing die we hebben ontwikkeld om in enkele minuten en enkele klikken inzicht te geven in onbewerkte tekst data. Deze toepassing zal in een toekomstig artikel worden gepresenteerd.

Example of the app that will be deployed on GCP

Voorbeeld van de app die zal worden geïmplementeerd op GCP

Er zijn twee hoofdopties om deze toepassing en dit proces te starten:

  • Ofwel de gebruiker kloont de GitHub repository op zijn computer, installeert alle afhankelijkheden en start de applicatie op een lokale omgeving.

  • Of de gebruiker heeft direct toegang tot de toepassing via een speciale URL zonder voorafgaande installatie.

Om de applicatie beschikbaar te maken voor het grootste aantal mensen binnen ons bedrijf, en dus voor mensen die niet per se gewend zijn om met GitHub om te gaan, hebben we besloten om de applicatie op GCP (Google Cloud Platform) te implementeren en toegankelijk te maken via een enkele URL in een beveiligde omgeving.

Stapsgewijze implementatie op GCP

Er zijn twee verschillende benaderingen getest om de toepassing op GCP te implementeren:

  • Cloud Run gebruiken

  • App Engine gebruiken

Er is echter een eerste gemeenschappelijke stap die beide benaderingen betreft, namelijk het “dockeriseren” van onze applicatie.

De applicatie Dockeriseren

Als u niet bekend bent met Docker, volgt hier een kleine introductie, maar aarzel niet om de documentatie of meer specifieke artikelen voor meer details.

Wat is docker?

Docker is een open platform voor het ontwikkelen, verzenden en uitvoeren van toepassingen. Het stelt u in staat om een applicatie met al haar afhankelijkheden te verpakken in een gestandaardiseerde eenheid voor softwareontwikkeling. In de praktijk betekent dit het bouwen van wat een Docker image wordt genoemd, d.w.z. de blauwdrukken van de toepassing die de basis vormen van Docker-containers, de inhoud in rust. Om deze image te bouwen, moeten we een Dockerfile definiëren, d.w.z. een eenvoudig tekstbestand dat een lijst met commando's bevat die de Docker-client aanroept tijdens het creëren van een image. Zodra het image is gebouwd, wordt het opgeslagen in een register (bijv. Container Registry op GCP) en kan het worden ingezet op een speciale instantie, bijvoorbeeld via Cloud Run of App Engine.

Daarom moeten we in ons geval:

  • Een Dockerbestand maken

  • Onze applicatie-afbeelding bouwen

  • De afbeelding opslaan in een register

Laten we beginnen met het aanmaken van de Dockerfile. Zoals eerder vermeld, bestaat dit uit een opeenvolging van commando's die gebruikt worden om de Docker-image aan te maken. In het geval van een Streamlit-toepassing kan de Dockerfile in verschillende blokken worden verdeeld:

  • Definieer de runtime-omgeving: in ons geval python 3.7

  • Definieer de poort waarop de toepassing zal draaien

  • Installeer de benodigde bibliotheken en hun afhankelijkheden met behulp van een requirements.txt-bestand

  • Kopieer de code van uw toepassing en definieer de werkdirectory van waaruit de toepassing wordt gestart

  • Definieer het commando om de toepassing uit te voeren

├── app.py <- Hoofdscript om de Streamlit app te starten
├── text_explorer <- Map met alle functies en code
├── requirements.txt <- Bestand met de benodigde bibliotheken om te installeren
└── referenties <- Map met logo's en afbeeldingen

Met deze structuur is hier een voorbeeld van de Dockerfile die we voor onze applicatie hebben gebruikt:

VAN python:3.7

# Laat de poort zien waarop u uw app wilt hebben
UITLAGEN 8080

# Upgrade pip en installatievereisten
COPY vereisten.txt vereisten.txt
RUN pip install -U pip
RUN pip install -r vereisten.txt

# Kopieer app code en stel werkmap in
COPY text_explorer text_explorer
KOPIEer app.py app.py
COPY referenties referenties
WORKDIR .

# Uitvoeren
ENTRYPOINT [“streamlit”, “run”, “app.py”, “-server.port=8080”, “-server.address=0.0.0.0”]

Zodra het Dockerbestand is aangemaakt, kunnen we ons image bouwen, waarbij we een GCP-vriendelijke naamgevingsconventie volgen die later bij de implementatie van pas zal komen. Dit gebeurt met het volgende commando:

docker build -t eu.gcr.io/gcp_project_name/app_name:v1 .

Om het aan uw eigen toepassing aan te passen, vervangt u de ‘gcp_project_naam’ door uw eigen GCP projectnaam en de ‘app_naam’ door uw eigen applicatienaam. U kunt het versienummer ook bijwerken naarmate uw applicatie evolueert door de ‘v1’ achtervoegsel met uw huidige versie.

Van daaruit kunnen we onze applicatie, verpakt in een docker image, deployen op GCP om het toegankelijk te maken voor onze teamgenoten.

Implementeer uw app met Cloud Run

Cloud Run is een GCP serverloze cloud dienst die gebruikt wordt om vooraf gebouwde toepassingen gemakkelijk te implementeren. Een van de belangrijkste voordelen is dat het het grootste deel van het resources managementproces automatiseert. Daarom hoeft u Cloud Run alleen maar te vertellen waar uw Docker image is, en Cloud Run zal het dan op een serverloze omgeving implementeren zonder dat u bijvoorbeeld het optimale aantal resources hoeft op te geven.

Om dat te doen, kunt u de onderstaande stappen volgen:

  • initialiseren gcloud module op het juiste GCP project met het volgende commando:

gcloud init

  • Push de docker naar de GCP Container Registry met het volgende commando:
docker push eu.gcr.io/gcp_project_name/app_name:v1
  1. Ga naar uw GCP project, naar de Cloud run sectie. Klik op “Create service”, kies de regio en definieer uw servicenaam. Selecteer vervolgens de Docker image die overeenkomt met uw Streamlit app en update de poort met degene die u gedefinieerd heeft in uw Dockerfile

Cloud Run-interface

  • Ten slotte kunt u uw app testen door de URL te volgen die gekoppeld is aan de nieuw aangemaakte Cloud Run-service

Zoals u kunt zien, gebeurt de implementatie in slechts een paar stappen en is deze vrij eenvoudig, zelfs voor nieuwkomers op het gebied van applicatie-implementatie. In ons geval wilden we echter naast de implementatie ook onze applicatie beveiligen, zodat deze alleen toegankelijk zou zijn binnen ons bedrijf, en op dat moment vonden we geen “gemakkelijke” oplossing die bij Cloud Run zou passen. Daarom besloten we op zoek te gaan naar een alternatieve oplossing waarmee we deze beveiligingslaag zonder al te veel problemen konden gebruiken en uiteindelijk kwamen we uit bij App Engine.

Uw app implementeren met App Engine

App Engine is een cloud-gebaseerde computerdienst die gebruikt wordt om webapps te hosten die al in de Google-infrastructuur zitten. In een notendop kunt u hiermee hetzelfde doen als met Cloud Run, in de zin dat het allebei Google cloud-diensten zijn waarmee u applicaties kunt implementeren. Maar in tegenstelling tot Cloud Run, waar u alleen betaalt voor de aanvragen die binnenkomen, betaalt u op App Engine voor de volledige draaitijd, of er nu aanvragen zijn of niet. Uiteindelijk kan App Engine dus een duurdere oplossing zijn. Desondanks hebben we toch voor deze oplossing gekozen omdat App Engine het voordeel heeft van een native integratie met IAP (Identity-Aware Proxy) waarmee u uw applicatie eenvoudig kunt beveiligen.

De stappen om een implementatie op App Engine te bereiken zijn niet talrijker of ingewikkelder dan voor Cloud Run, hier is wat u moet doen:

  • Controleer de poort in uw Dockefile, deze moet 8080 zijn om compatibel te zijn met App Engine.
  • Initialiseer de gcloud module op het rechter GCP project met het volgende commando:
gcloud init
  • Maak een YAML-bestand voor uw app (met de naam app.yaml) in de root van uw project (d.w.z. op hetzelfde niveau als uw hoofdscript en uw Dockerfile) met het volgende sjabloon:

app.yaml file exampleapp.yaml bestand voorbeeld

Werk de servicenaam bij met uw eigen applicatieservicenaam

Hier hebben we de optie runtime: custom gedefinieerd, omdat u met custom runtimes apps kunt bouwen die draaien in een omgeving die gedefinieerd is door een Dockerfile, zoals bij ons het geval is. De env:flex optie betekent dat onze applicatie in de flexibele omgeving zal draaien (in tegenstelling tot de standaard omgeving). Deze keuze is gemaakt omdat de flexibele omgeving de applicatie draait in Docker-containers op virtuele machines (VM's) van Google Compute Engine, die minder beperkingen hebben dan in de standaardomgeving (uw app kan bijvoorbeeld niet naar schijf schrijven). Meer details over de belangrijkste verschillen vindt u in de documentatie van Google.

U kunt ook meer gedetailleerde netwerk-, resources- en schaalinstellingen in het YAML-bestand opnemen, zoals het minimum aantal instanties dat aan uw service wordt gegeven of het aantal CPU's bijvoorbeeld. U kunt ook enkele omgevingsvariabelen in dat bestand definiëren om ze toegankelijk te maken voor uw applicatie.

  • Voer de volgende opdracht uit (dit kan enkele minuten duren):
gcloud app deploy app.yaml
  • Zodra u klaar bent met het deploy commando, zal de app beschikbaar zijn op App Engine en zult u zijn speciale URL direct op GCP vinden

Als u uw app wilt beveiligen en een beperkte toegang wilt geven aan sommige mensen, ga dan naar uw GCP project, in de “IAM & Admin” / “Identity-Aware Proxy” sectie:

  • In “Alle Webdiensten” zou u een sectie “App Engine app” moeten zien. Als IAP uit staat, zet het dan aan en klik op uw Streamlit service.

IAP-secties om machtigingen te beheren

  • Klik aan de rechterkant op “Add member” (Lid toevoegen), voer alle e-mailadressen in die u wilt (of een alias die gekoppeld is aan een mailinglijst) en selecteer de rol “IAP-secured Web App User” (Beveiligde gebruiker Web App).

En u bent klaar. Uw applicatie is nu geïmplementeerd en beveiligd.

Tips als u problemen hebt met de weergave van afbeeldingen in uw geïmplementeerde app

Wanneer u st.pyplot() of st.image() gebruikt, kunt u enkele weergaveproblemen tegenkomen wanneer u naar uw geïmplementeerde toepassing kijkt (d.w.z. “0” wordt weergegeven in plaats van uw plot of afbeelding). Wij raden u aan om waar mogelijk st.plotly_chart() te gebruiken om dit te vermijden en anders HTML code snippets te gebruiken. In ons geval wilden we bijvoorbeeld een aantal wordcloud's weergeven en dat kon niet met Plotly. Daarom besloten we om de wordcloud-afbeelding als PNG op te slaan in een speciale GCS-bucket, deze als bytes te downloaden en weer te geven met wat HTML-code zoals deze:

def display_wordcloud(image):
st.markdown(
f"""

""",
unsafe_allow_html=True
)
st.markdown("")
st.markdown("")

In dat voorbeeld is de variabele “image” een bytes-object afkomstig van de methode .dowload_as_bytes() van het Google cloud storage python pakket.

Conclusie

Het doel van dit artikel was om u enkele tips en voorbeelden te geven van cloud services die gebruikt kunnen worden voor het implementeren van Streamlit toepassingen. Onze ervaring is dat als u een beveiligingslaag nodig heeft om beperkte toegang tot sommige mensen te garanderen, App Engine de juiste oplossing is. Anders blijft Cloud Run een gemakkelijke manier om een Streamlit toepassing te implementeren.

Credits: Paul Devienne, Amale El Hamri