Dockerfile respectifspython3.9 , latest (dockerfile) Ces balises ne sont plus prises en charge ou entretenues, elles sont supprimées du référentiel GitHub, mais les dernières versions poussées pourraient toujours être disponibles dans Docker Hub si quelqu'un les tire:
python3.9-alpine3.13python3.8python3.8-alpine3.11python3.7python3.7-alpine3.8python3.6python3.6-alpine3.8python2.7Les étiquettes de dernière date pour ces versions sont:
python3.9-alpine3.13-2024-03-11python3.8-2024-10-28python3.8-alpine3.11-2024-03-11python3.7-2024-10-28python3.7-alpine3.8-2024-03-11python3.6-2022-11-25python3.6-alpine3.8-2022-11-25python2.7-2022-11-25 Remarque : il y a des balises pour chaque date de construction. Si vous devez "épingler" la version Docker Image que vous utilisez, vous pouvez sélectionner l'une de ces balises. Par exemple tiangolo/meinheld-gunicorn-flask:python3.9-2024-11-02 .
Docker Image avec Meinheld géré par Gunicorn pour des applications Web haute performance dans Flask en utilisant Python avec des performances automatique.
Github Repo : https://github.com/tiangolo/meinheld-gunicorn-flask-docker
Docker Hub Image : https://hub.docker.com/r/tiangolo/meinheld-gunicorn-flask/
Les applications Web Python Flask fonctionnant avec Meinheld contrôlé par Gunicorn ont certaines des meilleures performances réalisables par Flask (*).
Si vous avez une application déjà existante dans FLASK ou en construisez une nouvelle, cette image vous donnera les meilleures performances possibles (ou à proximité).
Cette image a un mécanisme de "réglage automatique" inclus, afin que vous puissiez simplement ajouter votre code et obtenir de bonnes performances automatiquement. Et sans faire de sacrifices (comme la journalisation).
La dernière version actuelle de Meinheld sorti est de 1,0,2, à partir du 17 mai 2020. Cette version de Meinheld nécessite une ancienne version de Greenlet ( >=0.4.5,<0.5 ) qui n'est pas compatible avec Python 3.10 et 3.11. C'est pourquoi la dernière version de Python prise en charge dans cette image est Python 3.9.
Si vous créez un nouveau projet, vous pourriez bénéficier d'un cadre plus récent et plus rapide comme Fastapi (basé sur ASGI au lieu de WSGI comme Flask et Django), et une image Docker comme Tiangolo / Uvicorn-Gunicorn-Fastapi .
Cela vous donnerait environ 200% les performances réalisables avec Flask, même lors de l'utilisation de cette image.
De plus, si vous souhaitez utiliser de nouvelles technologies comme WebSockets, ce serait plus facile avec un cadre plus récent basé sur ASGI, comme Fastapi . Comme l'ASGI standard a été conçu pour être en mesure de gérer le code asynchrone comme celui nécessaire pour WebSockets.
Meinheld est un serveur Web compatible WSGI haute performance.
Vous pouvez utiliser Gunicorn pour gérer Meinheld et en exécuter plusieurs processus.
Flask est un microframe pour Python basé sur Werkzug, Jinja 2 et Bonnes intentions.
Cette image a été créée pour être une alternative à Tiangolo / Uwsgi-nginx-FLASK , offrant à environ 400% les performances de cette image.
Il est basé sur l'image plus générique Tiangolo / Meinheld-Gunicorn . C'est celui que vous utiliseriez pour d'autres frameworks WSGI, comme Django.
Vous utilisez probablement des kubernetes ou des outils similaires. Dans ce cas, vous n'avez probablement pas besoin de cette image (ou de toute autre image de base similaire ). Vous feriez probablement mieux de construire une image Docker à partir de zéro .
Si vous avez un groupe de machines avec Kubernetes , Mode Swarm Docker, Nomad ou autre système complexe similaire pour gérer des conteneurs distribués sur plusieurs machines, vous voudrez probablement gérer la réplication au niveau du cluster au lieu d'utiliser un gestionnaire de processus dans chaque conteneur qui démarre plusieurs processus de travail , ce que fait cette image Docker.
Dans ces cas (par exemple, à l'aide de Kubernetes), vous voudriez probablement créer une image Docker à partir de zéro , installer vos dépendances et exécuter un seul processus au lieu de cette image.
Par exemple, en utilisant Gunicorn, vous pourriez avoir une app/gunicorn_conf.py avec:
# Gunicorn config variables
loglevel = "info"
errorlog = "-" # stderr
accesslog = "-" # stdout
worker_tmp_dir = "/dev/shm"
graceful_timeout = 120
timeout = 120
keepalive = 5
threads = 3 Et puis vous pourriez avoir un Dockerfile avec:
FROM python:3.9
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app
CMD [ "gunicorn" , "--conf" , "app/gunicorn_conf.py" , "--bind" , "0.0.0.0:80" , "app.main:app" ]Vous pouvez en savoir plus sur ces idées dans la documentation Fastapi sur: Fastapi dans les conteneurs - Docker comme les mêmes idées s'appliqueraient à d'autres applications Web dans des conteneurs.
Vous pouvez vouloir un gestionnaire de processus exécutant plusieurs processus de travail dans le conteneur si votre application est suffisamment simple pour que vous n'ayez pas besoin (du moins pas encore) pour affiner le nombre de processus trop, et vous pouvez simplement utiliser un défaut automatisé, et vous l'exécutez sur un seul serveur , pas un cluster.
Vous pouvez vous déployer sur un seul serveur (pas un cluster) avec Docker Compose , vous n'auriez donc pas de moyen facile de gérer la réplication des conteneurs (avec Docker Compose) tout en préservant le réseau partagé et l'équilibrage de charge .
Ensuite, vous pouvez avoir un seul conteneur avec un gestionnaire de processus commençant plusieurs processus de travail à l'intérieur, comme le fait cette image Docker.
Vous pourriez également avoir d'autres raisons qui faciliteraient le fait d'avoir un seul conteneur avec plusieurs processus au lieu d'avoir plusieurs conteneurs avec un seul processus dans chacun d'eux.
Par exemple (selon votre configuration), vous pouvez avoir un outil comme un exportateur de Prométhée dans le même conteneur qui devrait avoir accès à chacune des demandes qui arrivent.
Dans ce cas, si vous aviez plusieurs conteneurs , par défaut, lorsque Prometheus est venu lire les mesures , il obtiendrait ceux d' un seul conteneur à chaque fois (pour le conteneur qui a géré cette demande particulière), au lieu d'obtenir les métriques accumulées pour tous les conteneurs répliqués.
Ensuite, dans ce cas, il pourrait être plus simple d'avoir un conteneur avec plusieurs processus , et un outil local (par exemple un exportateur de Prométhée) sur le même conteneur collectant des mesures Prometheus pour tous les processus internes et exposant ces mesures sur ce seul conteneur.
En savoir plus sur tout cela dans la documentation Fastapi sur: Fastapi dans les conteneurs - Docker, car les mêmes concepts s'appliquent aux autres applications Web dans des conteneurs.
Vous n'avez pas à cloner ce dépôt.
Vous pouvez utiliser cette image comme image de base pour d'autres images.
En supposant que vous avez un fichier requirements.txt , vous pouvez avoir un Dockerfile comme celui-ci:
FROM tiangolo/meinheld-gunicorn-flask:python3.9
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./app /app Il s'attendra à un fichier sur /app/app/main.py .
Ou autrement un fichier sur /app/main.py .
Et s'attendra à ce qu'il contienne une app variable avec votre application "WSGI".
Ensuite, vous pouvez créer votre image à partir du répertoire qui a votre Dockerfile , par exemple:
docker build -t myimage ./Ce sont les variables d'environnement que vous pouvez définir dans le conteneur pour le configurer et leurs valeurs par défaut:
MODULE_NAMELe "module" (fichier "Python à importer par Gunicorn, ce module contiendrait l'application de ballon réelle dans une variable.
Par défaut:
app.main s'il y a un fichier /app/app/main.py oumain s'il y a un fichier /app/main.py Par exemple, si votre fichier principal était sur /app/custom_app/custom_main.py , vous pouvez le définir comme:
docker run -d -p 80:80 -e MODULE_NAME= " custom_app.custom_main " myimageVARIABLE_NAMELa variable à l'intérieur du module Python qui contient l'application Flask.
Par défaut:
appPar exemple, si votre fichier Python principal a quelque chose comme:
from flask import Flask
api = Flask ( __name__ )
@ api . route ( "/" )
def hello ():
return "Hello World from Flask" Dans ce cas, api serait la variable avec "l'application FLASK". Vous pouvez le définir comme:
docker run -d -p 80:80 -e VARIABLE_NAME= " api " myimageAPP_MODULELa chaîne avec le module Python et le nom de variable passaient à Gunicorn.
Par défaut, défini basé sur les variables MODULE_NAME et VARIABLE_NAME :
app.main:app oumain:appVous pouvez le définir comme:
docker run -d -p 80:80 -e APP_MODULE= " custom_app.custom_main:api " myimageGUNICORN_CONFLe chemin vers un fichier de configuration de Python Gunicorn.
Par défaut:
/app/gunicorn_conf.py s'il existe/app/app/gunicorn_conf.py s'il existe/gunicorn_conf.py (la valeur par défaut incluse)Vous pouvez le définir comme:
docker run -d -p 80:80 -e GUNICORN_CONF= " /app/custom_gunicorn_conf.py " myimageWORKERS_PER_CORECette image vérifiera le nombre de cœurs CPU disponibles dans le serveur actuel exécutant votre conteneur.
Il définira le nombre de travailleurs sur le nombre de cœurs CPU multipliés par cette valeur.
Par défaut:
2Vous pouvez le définir comme:
docker run -d -p 80:80 -e WORKERS_PER_CORE= " 3 " myimage Si vous avez utilisé la valeur 3 dans un serveur avec 2 cœurs CPU, il exécuterait 6 processus de travail.
Vous pouvez également utiliser des valeurs de points flottants.
Ainsi, par exemple, si vous avez un grand serveur (disons, avec 8 cœurs de processeur) exécutant plusieurs applications, et vous avez une application ASGI qui, vous savez, n'aura pas besoin de performances élevées. Et vous ne voulez pas gaspiller les ressources du serveur. Vous pouvez le faire utiliser 0.5 travailleurs par noyau CPU. Par exemple:
docker run -d -p 80:80 -e WORKERS_PER_CORE= " 0.5 " myimageDans un serveur avec 8 cœurs CPU, cela ne ferait démarrer que 4 processus de travail.
WEB_CONCURRENCYRemplacez la définition automatique du nombre de travailleurs.
Par défaut:
WORKERS_PER_CORE . Ainsi, dans un serveur avec 2 cœurs, par défaut, il sera défini sur 4 .Vous pouvez le définir comme:
docker run -d -p 80:80 -e WEB_CONCURRENCY= " 2 " myimageCela rendrait l'image à démarrer 2 processus de travail, indépendamment du nombre de cœurs de processeur disponibles dans le serveur.
HOSTL'hôte utilisé par Gunicorn, l'IP où Gunicorn écoutera les demandes.
C'est l'hôte à l'intérieur du conteneur.
Ainsi, par exemple, si vous définissez cette variable sur 127.0.0.1 , elle ne sera disponible que dans le conteneur, pas dans l'hôte qui l'exécute.
Il est prévu pour l'exhaustivité, mais vous ne devriez probablement pas le changer.
Par défaut:
0.0.0.0PORTLe port sur lequel le conteneur doit écouter.
Si vous exécutez votre conteneur dans un environnement restrictif qui vous oblige à utiliser un port spécifique (comme 8080 ), vous pouvez le définir avec cette variable.
Par défaut:
80Vous pouvez le définir comme:
docker run -d -p 80:8080 -e PORT= " 8080 " myimageBINDL'hôte et le port réels sont passés à Gunicorn.
Par défaut, défini basé sur HOST et PORT variables.
Donc, si vous n'avez rien changé, il sera défini par défaut sur:
0.0.0.0:80Vous pouvez le définir comme:
docker run -d -p 80:8080 -e BIND= " 0.0.0.0:8080 " myimageLOG_LEVELLe niveau de journal pour Gunicorn.
Un des:
debuginfowarningerrorcritical Par défaut, défini sur info .
Si vous avez besoin de presser plus de performances sacrifiant la journalisation, définissez-la dans warning , par exemple:
Vous pouvez le définir comme:
docker run -d -p 80:8080 -e LOG_LEVEL= " warning " myimage Les journaux sont envoyés au stderr et stdout du conteneur, ce qui signifie que vous pouvez afficher les journaux avec les docker logs -f your_container_name_here commande_Container_name_here.
L'image comprend un fichier de configuration de python Gunicorn par défaut sur /gunicorn_conf.py .
Il utilise les variables d'environnement déclarées ci-dessus pour définir toutes les configurations.
Vous pouvez le remplacer en incluant un fichier dans:
/app/gunicorn_conf.py/app/app/gunicorn_conf.py/gunicorn_conf.py/app/prestart.sh Si vous devez exécuter quelque chose avant de démarrer l'application, vous pouvez ajouter un fichier prestart.sh au répertoire /app . L'image détectera et l'exécutera automatiquement avant de tout démarrer.
Par exemple, si vous souhaitez ajouter des migrations SQL Alembic (avec SQLALCHEMY), vous pouvez créer un fichier ./app/prestart.sh dans votre répertoire de code (qui sera copié par votre Dockerfile ) avec:
#! /usr/bin/env bash
# Let the DB start
sleep 10 ;
# Run migrations
alembic upgrade head Et il attendrait 10 secondes pour donner à la base de données un peu de temps pour démarrer, puis exécuter cette commande alembic .
Si vous avez besoin d'exécuter un script Python avant de démarrer l'application, vous pouvez faire en sorte que le fichier /app/prestart.sh exécute votre script Python, avec quelque chose comme:
#! /usr/bin/env bash
# Run custom Python script before starting
python /app/my_custom_prestart_script.py En bref: vous ne devriez probablement pas utiliser Alpine pour les projets Python, utilisez plutôt les versions slim Docker Image.
Voulez-vous plus de détails? Continuer la lecture?
Alpine est plus utile pour d'autres langues où vous construisez un binaire statique dans une étape d'image Docker (en utilisant le bâtiment Docker en plusieurs étapes), puis le copiez sur une simple image alpine, puis exécutez simplement ce binaire. Par exemple, en utilisant Go.
Mais pour Python, car Alpine n'utilise pas l'outillage standard utilisé pour construire des extensions de Python, lors de l'installation de packages, dans de nombreux cas, Python ( pip ) ne trouvera pas un package installable précompilé (une "roue") pour Alpine. Et après le débogage de nombreuses erreurs étranges, vous vous rendrez compte que vous devez installer beaucoup d'outils supplémentaires et créer beaucoup de dépendances juste pour utiliser certains de ces packages Python courants. ?
Cela signifie que, bien que l'image alpine d'origine ait pu être petite, vous vous retrouvez avec une image avec une taille comparable à la taille que vous auriez obtenue si vous veniez d'utiliser une image python standard (basée sur Debian), ou dans certains cas encore plus grande. ?
Et dans tous ces cas, il faudra beaucoup plus de temps pour construire, consommer beaucoup plus de ressources, construire des dépendances plus longtemps et augmenter son empreinte carbone, car vous utilisez plus de temps et d'énergie CPU pour chaque construction. ?
Si vous voulez des images Slim Python, vous devriez plutôt essayer d'utiliser les versions slim qui sont toujours basées sur Debian, mais qui sont plus petites. ?
Toutes les balises d'image, les configurations, les variables d'environnement et les options d'application sont testées.
issue-manager.yml . PR # 154 par @tiangolo.latest-changes . PR # 153 par @tiangolo.latest-changes.yml . PR # 141 par @alejsdev.README.md . PR # 137 par @alejsdev. Faits saillants de cette version:
Prise en charge de Python 3.9 et 3.8.
Dépréciation de Python 3.6 et 2.7.
python3.6-2022-11-25 et python2.7-2022-11-25 .Versions améliorées de toutes les dépendances.
Petites améliorations et correctifs.
Ajoutez la prise en charge de Python 3.9 et Python 3.9 Alpine. PR # 50 par @tiangolo.
Ajoutez Python 3.8 avec Alpine 3.11. PR # 28.
Ajoutez la prise en charge de Python 3.8. PR # 27.
tiangolo/meinheld-gunicorn-flask:python3.7-2019-10-15 . PR # 17.Ajoutez une prise en charge de Python 2.7 (vous devez utiliser Python 3.7 ou Python 3.6). PR # 11.
Mettre à jour la configuration de Travis CI. PR # 10 par @cclauss.
/app/prestart.sh . Ce projet est concédé sous licence de la licence du MIT.