Aller au contenu
Cheat Sheet
Python

Accéder à un serveur qui tourne sur Google Colab

Google Colab est une excellente façon de créer des Jupyter notebooks (*.ipynb) en bénéficiant gratuitement de puissance de calcul CPU / GPU.
Le problème c’est que lorsqu’on crée une application de type « serveur » comme Uvicron, Flask, Streamlit, … (qui s’accède normalement depuis une URL locale du genre « 127.0.0.1:8000 »), il n’est pas possible d’y accéder directement.

TLDR;

  • Quand on lance un serveur depuis Google Colab, on est censé y accéder depuis une IP locale.
    Par exemple : http://127.0.0.1:8000
    Cette IP n’est pas accessible. Même en utilisant l’IP publique du serveur, ça ne fonctionne pas.
  • On peut utiliser ngrok qui permet de créer un tunnel vers un serveur accessible publiquement.
    Le problème de ngrok est qu’il nous fait changer d’IP à chaque exécution, ce qui est pénible lorsqu’on est en phase de développement / debug.
  • Une solution est de créer un tunnel SSH avec redirection de port vers un serveur public et de faire en sorte que la connexion tourne en tache de fond avec nohup.

Création d’un serveur simple sur Google Colab

Voici à quoi ressemble un Google Colab proposant un simple serveur Uvicorn / FastAPI :

!pip install FastAPI uvicorn nest_asyncio

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=['*'],
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*'],
)

@app.get("/")
async def root():
    return {"message": "Hello World !"}

import uvicorn
import nest_asyncio
# Apply nest_asyncio to allow running uvicorn in Colab
nest_asyncio.apply()
uvicorn.run(app, port=8000)

Lorsqu’on exécute ce code, on obtient :

INFO:     Started server process [303]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

On constate que l’URL proposée est une URL locale et qu’on ne peut pas y accéder.

Créer un tunnel avec Ngrok

Ngrok est un service qui permet (entre autres) de servir des applications web depuis une URL statique.
C’est par exemple utile lorsqu’on développe quelque chose en local sur son poste et qu’on souhaite le présenter à un collègue sans passer par la publication sur un serveur web.

NGroq propose une version gratuite qui permet d’accéder à quelques fonctionnalités, qui nous suffiront pour notre cas d’usage : https://ngrok.com/pricing

Récupérer une clé d’API sur NGrok

Une fois son compte NGrok créé, il faut aller à l’URL https://dashboard.ngrok.com/get-started/your-authtoken pour récupérer sa clé d’API.

Ajouter la clé d’API en tant que « secret » sur Colab

Le meilleur moyen de ne pas enregistrer directement ses clés d’API dans le Jupiter Notebook, c’est de le stocker en tant que « secret » dans Google Colab.

On y accède depuis l’icône en forme de clé dans le panneau de gauche. On ajoute un « secret » auquel on donne le nom NGROK_API_KEY. On s’assure qu’il est accessible depuis ce notebook.

Pour accéder à un « secret » depuis le code Python, on fait :

from google.colab import userdata
userdata.get('secretName')

Lancer Uvicorn en passant par Ngrok

Pour lancer notre serveur Uvicorn en passant par NGrok, on utilisera le code suivant :

!pip install pyngrok

from pyngrok import ngrok
import uvicorn
import nest_asyncio
from google.colab import userdata

# Get your authtoken from https://dashboard.ngrok.com/get-started/your-authtoken
auth_token = userdata.get('NGROK_API_KEY')
ngrok.set_auth_token(auth_token)
ngrok_tunnel = ngrok.connect(8000)
print('Public URL:', ngrok_tunnel.public_url)

nest_asyncio.apply()
uvicorn.run(app, port=8000)

Ce code va créer un tunnel entre le port 8000 de notre instance locale et un serveur hébergé par Ngrok accessible par une URL publique, que l’on affiche.
En lançant notre serveur Uvicorn sur le port 8000, il sera alors accessible par l’URL publique.

Le code suivant va retourner :

INFO:     Started server process [1655]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Public URL: https://1234-56-78-91-011.ngrok-free.app

l’inconvénient de cette technique, c’est que lorsqu’on arrête le serveur Uvicorn, le tunnel avec Ngrok est interrompu. Lorsqu’on relancera le serveur Uvicorn, notre tunnel Ngrok sera sur une nouvelle URL.
Pour éviter ça, il y a plusieurs solutions :

  • Prendre un abonnement payant chez Ngrok qui permet d’avoir des URL réutilisables.
  • Utiliser une autre méthode pour faire son tunnel.

Jupiter notebook de l’exemple : https://github.com/Yajusta/GoogleColab/blob/main/POC/FastAPI_with_NGROK_tunnel_POC.ipynb

Créer un tunnel SSH avec redirection de port

Il existe plusieurs services qui permettent de rediriger un port local vers une URL publique grâce à un tunnel SSH.

Par exemple :

  • https://localhost.run
  • https://serveo.net

Le problème avec cette technique, c’est que si on crée le tunnel depuis un script Python, dès qu’on arrête l’exécution du code Python le tunnel s’arrête et on changera (encore) d’URL publique au prochain lancement de notre serveur.

L’astuce consiste donc a exécuter le tunnel SSH depuis une commande shell, tout en la laissant tourner en arrière plan.
Pour cela, nous utilisons la commande nohup couplée à & . Lorsqu’on utilise nohup, la sortie standard n’est pas affichée mais enregistrée dans un fichier texte (nohup.out). Il faut donc afficher le contenu de ce fichier afin de connaitre l’URL publique qui nous est attribuée.

Le script suivant permet de faire toutes ces actions, et même supprimer les anciennes connexions SSH potentiellement existantes.

!rm -f nohup.out
!ps aux | grep '[s]sh' | awk '{print $2}' | xargs kill -9
!nohup ssh -o StrictHostKeyChecking=no -R 80:localhost:8000 serveo.net &
!ps -edf | grep ssh
!sleep 3
!cat nohup.out

En détail :

  • !rm -f nohup.out : on supprime le fichier nohup.out qui a potentiellement été créé lors de la dernière exécution. Comme nohup concatène dans le fichier de sortie, on ne souhaite pas afficher les informations qui concernent les précédentes exécutions.
  • !ps aux | grep '[s]sh' | awk '{print $2}' | xargs kill -9 : on recherche s’il y a des process ssh en train de tourner et on les tue avec kill -9. L’utilisation de [s]sh permet de faire en sorte que la commande en elle même ne ressorte pas dans le grep.
  • !nohup ssh -o StrictHostKeyChecking=no -R 80:localhost:8000 serveo.net & : on redirige le port 8000 local vers le port 80 de serveo.net. -o StrictHostKeyChecking=no permet de ne pas avoir de question sur les clés de sécurité SSH. & permet de faire en sorte que le processus soit lancer en arrière plan.
  • !sleep 3 : on attend 3 secondes, le temps de laisser le service effectuer sa connexion.
  • cat nohup.out : on affiche sur la sortie standard le contenu du fichier nohup.out, c’est à dire la réponse de la connexion SSH.

La sortie ressemblera à :

nohup: appending output to 'nohup.out'
root 33330 1 0 17:02 ? 00:00:00 ssh -o StrictHostKeyChecking=no -R 80:localhost:
root 33331 303 0 17:02 ? 00:00:00 /bin/bash -c ps -edf | grep ssh
root 33333 33331 0 17:02 ? 00:00:00 grep ssh
Pseudo-terminal will not be allocated because stdin is not a terminal.
Forwarding HTTP traffic from https://1234567890azertyuiopqsdfghjklm.serveo.net

L’URL https://1234567890azertyuiopqsdfghjklm.serveo.net sera donc notre URL publique d’accès.

Grâce à cette méthode, on peut lancer notre serveur Uvicorn et le stopper autant de fois qu’on le souhaite, notre URL publique restera la même pendant tout le temps de notre session !

Jupiter notebook de l’exemple : https://github.com/Yajusta/GoogleColab/blob/main/POC/FastAPI_with_SSH_tunnel_POC.ipynb

Jupiter notebook d’exemple avec Streamlit : https://github.com/Yajusta/GoogleColab/blob/main/POC/Streamlit_with_SSH_tunnel_POC.ipynb

Article rédigé par Yajusta.

Yajusta : Optimisez votre productivité avec des solutions sur-mesure.
💡 Vous avez une idée pour simplifier vos processus ?
⚙️ « Il y a juste à » la mettre en place ?
🚫 Mais vous n’avez pas les compétences techniques pour le faire ?
✅ Chez Yajusta, nous transformons vos défis en solutions concrètes.

https://www.yajusta.fr
Comment vérifier que mon client Torrent est bien derrière mon VPN ?
Créer une application Android avec Flet
fastapi flask Google Colab ngrok python ssh streamlit uvicorn

Articles similaires

Pylance / Pyright fait ramer…
Créer une application Android avec…
[Python] Comment bien démarrer un…
[Python] Extraire une page PDF…
[Python] Protocol
[Python] Liste de choix en…
[Python] Benedict : une autre…
[Python] Exécuter un programme externe…
Un package Python nécessite Visual…
Publier un site Flask sur…

Catégories

  • Android
  • Calibre
  • Docker
  • Excel
  • Git
  • Google Sheet
  • Knime
  • Linux
  • Logiciels
  • Matériel
  • Non classé
  • Notepad++
  • PHP
  • Power BI
  • Programmation
  • Python
  • Qlik
  • Service
  • Synology
  • Visual Studio Code
  • VSCode
  • Windows
  • Word
  • WordPress

Étiquettes

adb android apache audio calibre convertion css debian docker drivers excel fichiers firefox flask google grep html kobo linux manette markdown mp3 notepad++ office php pip portable privoxy python qlik qliksense qlikview realtek selenium synology tor venv vim virtualenv vscode web windows wordpress xargs youtube

Tags

adb android apache audio calibre convertion css debian docker drivers excel fichiers firefox flask google grep html kobo linux manette markdown mp3 notepad++ office php pip portable privoxy python qlik qliksense qlikview realtek selenium synology tor venv vim virtualenv vscode web windows wordpress xargs youtube
Thème par Colorlib Propulsé par WordPress