Heroku pour déployer votre application Python/Flask dans le cloud
Pierre Gradot
Posted on September 2, 2021
Vous avez développé une application Python à l'aide du framework Flask. Tout se passe bien sur votre poste et maintenant, vous vous demandez comment rendre ça accessible au monde entier ? Avec Heroku, c'est trivial, et c'est ce qu'on va voir dans cet article !
Heroku est une Platform as a Service (PaaS) dont le but est justement de déployer des applications le plus facilement possible dans le cloud. Ici, on ne configurera aucun serveur, on n'installera pas un environnement complet. On va juste écrire notre application avec Python et Flask, puis on va la pousser sur Heroku. On va l'accompagner de quelques petits fichiers de configuration pour expliquer à Heroku comment la lancer. Et c'est tout !
Le but de cet article n'est pas de faire un tutoriel complet sur Flask et Heroku. On va donc faire une application très simple, avec une seule route, juste pour afficher "hello, world". On va la tester en local sur notre PC avant de la déployer sur Heroku avec une configuration basique mais fonctionnelle.
Créer son application Flask
Installation
La première étape est d'installer Flask. Le plus simple est de faire :
pip install flask
Si vous voulez plus de finesse dans votre installation, comme par exemple utiliser un virtual environment, je vous laisse consulter la section Installation de la documentation officielle.
Code
En s'inspirant du quickstart guide officiel, on écrit notre main.py
:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'hello, world'
Je suis sous Windows, j'utilise dans un virtual environment, je me suis donc créé un petit script run.bat
pour lancer facilement mon application :
set FLASK_APP=main.py
.\venv\Scripts\flask run
C'est un peu surprenant quand on est habitué au développement en Python : on n'exécute pas directement notre script avec python
mais on dit à flask
quel fichier décrit notre application grâce à une variable d'environnement.
Quand on exécute flask
, il démarre un serveur local, par défaut sur le port 5000, pour servir notre application :
C:\python_flask_heroku>.\venv\bin\flask run
* Serving Flask app "main.py"
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Notez le warning au lancement : par défaut, Flask utilise un serveur fait pour le développement mais déconseillé pour la production. On verra dans la suite que ça impactera notre déploiement sur Heroku, puisqu'on voudra utiliser un serveur d'application plus adapté.
Pour vérifier que notre application fonctionne, il suffit d'ouvrir le lien donné dans les logs avec Firefox :
Simple, efficace, fonctionnel.
Dans ma console, je vois les logs des requêtes faites au serveur :
127.0.0.1 - - [22/Apr/2021 11:56:20] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [22/Apr/2021 11:58:30] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [22/Apr/2021 11:58:38] "GET /try HTTP/1.1" 404 -
Ici, il y a eu 2 accès sur la racine /
du serveur qui ont fonctionné avec le code 200, ainsi qu'un accès à /try
qui a échoué avec le code 404. En effet, mon application définit bien une route vers /
, mais pas vers /try
.
Mon application est prête, il ne reste plus qu'à la rendre accessible sur l'internet mondial grâce à Heroku.
Déploiement sur Heroku
Inscription et installation
Pour commencer, il faut créer un compte et installer l'interface en ligne de commande.
La commande heroku
est désormais disponible depuis le terminal et nous pouvons nous connecter à notre compte avec heroku login
. Une page internet s'ouvre dans notre navigateur par défaut pour entrer nos identifiants.
Créer son application
Le concept est totalement génial : le déploiement consiste juste à faire un git push
vers un dépôt distant qui est sur Heroku. Ce Git contient le code ainsi que des fichiers de configuration pour expliquer à Heroku comment lancer tout ça.
On a déjà une application fonctionnelle en local, on va donc créer un dépôt Git avec git init
.
On crée ensuite l'application Heroku, en lui donnant ou pas un nom. Dans mon cas, j'ai choisi de la nommer :
$ heroku apps
You have no apps.
$ heroku apps:create younup-flask
Creating ⬢ younup-flask... done
https://younup-flask.herokuapp.com/ | https://git.heroku.com/younup-flask.git
$ heroku apps
=== p.gradot@younup.fr Apps
younup-flask
Comme le dépôt existe déjà en local, les remotes sont ajoutées automatiquement :
$ git remote -v
heroku https://git.heroku.com/younup-flask.git (fetch)
heroku https://git.heroku.com/younup-flask.git (push)
L'adresse de mon application est déjà accessible, mais il n'y a pas grand chose d'intéressant...
D'ailleurs, elle est normalement toujours accessible (mais peut-être qu'un jour je la désactiverai....).
Configuration
Sur notre PC, l'interpréteur Python est installé ainsi que les paquets nécessaires. Par défaut, Heroku ne sait pas ce dont notre application a besoin, il faut donc lui préciser tout ça. Pour ça, il faut créer deux fichiers qu'on ajoute au dépôt Git.
Le premier est runtime.txt
dans lequel on indique la version de Python qu'on souhaite utiliser. Il y a une seule ligne dans ce fichier :
python-3.9.2
Le second est requirements.txt
, qui sert à pip
pour connaitre les paquets à installer :
flask
gunicorn
flask
, OK. Mais pourquoi gunicorn
? Souvenez-vous plus haut d'un warning lors du lancement de Flask, nous conseillant de "Use a production WSGI server instead". Et bien c'est exactement ce qu'est gunicorn
:
Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for UNIX. It's a pre-fork worker model. The Gunicorn server is broadly compatible with various web frameworks, simply implemented, light on server resources, and fairly speedy.
Pour expliquer à Heroku qu'il faut utiliser gunicorn
pour servir notre application Flask, on va utiliser le fichier Procfile
:
Heroku apps include a Procfile that specifies the commands that are executed by the app on startup. You can use a Procfile to declare a variety of process types, including your app’s web server".
Une ligne suffit pour notre Procfile
:
web: gunicorn main:app
Test en local
Heroku nous permet de tester en local avec la commande heroku local
.
Malheureusement, ce n'est pas possible dans mon cas car je suis sous Windows et gunicorn ne fonctionne pas Windows. Si vous êtes sous Linux ou macOS, vous pouvez exécuter cette commande pour vérifier que tout est OK avant de passer au déploiement.
Déploiment sur l'internet mondial
Tout est OK ? Il suffit de faire git commit
et git push
:
$ git push --set-upstream heroku master
Énumération des objets: 6, fait.
Décompte des objets: 100% (6/6), fait.
Compression par delta en utilisant jusqu'à 4 fils d'exécution
Compression des objets: 100% (3/3), fait.
Écriture des objets: 100% (6/6), 1.18 Kio | 1.18 Mio/s, fait.
Total 6 (delta 0), réutilisés 0 (delta 0), réutilisés du pack 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Python app detected
remote: ! Python has released a security update! Please consider upgrading to python-3.9.4
remote: Learn More: https://devcenter.heroku.com/articles/python-runtimes
remote: -----> Installing python-3.9.2
remote: -----> Installing pip 20.2.4, setuptools 47.1.1 and wheel 0.36.2
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote: Collecting flask
remote: Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB)
remote: Collecting gunicorn
remote: Downloading gunicorn-20.1.0.tar.gz (370 kB)
remote: Collecting itsdangerous>=0.24
remote: Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
remote: Collecting Werkzeug>=0.15
remote: Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
remote: Collecting click>=5.1
remote: Downloading click-7.1.2-py2.py3-none-any.whl (82 kB)
remote: Collecting Jinja2>=2.10.1
remote: Downloading Jinja2-2.11.3-py2.py3-none-any.whl (125 kB)
remote: Collecting MarkupSafe>=0.23
remote: Downloading MarkupSafe-1.1.1-cp39-cp39-manylinux2010_x86_64.whl (32 kB)
remote: Building wheels for collected packages: gunicorn
remote: Building wheel for gunicorn (setup.py): started
remote: Building wheel for gunicorn (setup.py): finished with status 'done'
remote: Created wheel for gunicorn: filename=gunicorn-20.1.0-py3-none-any.whl size=78917 sha256=389135bf7e57c6bee7f1675ce59482c4d7ab3500ab4debf1c633e23986c5326c
remote: Stored in directory: /tmp/pip-ephem-wheel-cache-c0xwgcsz/wheels/ee/ca/72/3e9be4033d3993d4d78e2f4accdfcfff6c690921fef5ea0d57
remote: Successfully built gunicorn
remote: Installing collected packages: colorama, itsdangerous, Werkzeug, click, MarkupSafe, Jinja2, flask, gunicorn
remote: Successfully installed Jinja2-2.11.3 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 colorama-0.4.4 flask-1.1.2 gunicorn-20.1.0 itsdangerous-1.1.0
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 52.6M
remote: -----> Launching...
remote: Released v3
remote: https://younup-flask.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/younup-flask.git
* [new branch] master -> master
C'est magnifique. Heroku nous installe l'interpréteur Python et les paquets indiqués avec pip
, puis il redémarre notre application, qui est maintenant disponible :
Publier une mise à jour
En fait, notre premier push était déjà une mise à jour. Les mises à jour suivantes se font de la même façon. Imaginons qu'on souhaite mettre à jour notre version de Python, pour suivre la recommandation donnée dans les logs d'installation : "Python has released a security update! Please consider upgrading to python-3.9.4". On modifie le fichier runtime.txt
, on commit, on push, et le processus d'installation et de déploiement recommence. Cette fois, par contre, on lira :
remote: -----> Python app detected
remote: -----> Found python-3.9.2, removing
remote: -----> No change in requirements detected, installing from cache
remote: -----> Installing python-3.9.4
Conclusion
Nous avons vu comment déployer très simplement notre application Flask sur Heroku et ainsi la rendre accessible au monde entier. Nous avons utilisé un compte gratuit, suffisant pour des tests, des hobbyists, des petites applications. Si vous avez des besoins plus importants, il existe des versions payantes.
Heroku supporte plusieurs autres langages out-of-the-box et fournit des getting started guides pour chacun d'eux. Il y a des astuces pour utiliser d'autres langages. Certains se servent de Docker (par exemple pour faire du C#) ; d'autres utilisent le système de buildpacks (par exemple pour faire du C).
Désormais, vous ne pourrez plus dire "je ne sais pas comment mettre mon application dans le cloud" !
Merci d'avoir lu cet article ! Il a été posté initialement sur le blog de Younup.
Posted on September 2, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.