Dockerfile respectifspython3.12 , latest (dockerfile)python3.11 , (dockerfile)python3.10 (dockerfile)python3.9 , (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.8python3.8-alpinepython3.7python3.6python2.7Les étiquettes de dernière date pour ces versions sont:
python3.8-2024-10-28python3.8-alpine-2024-03-11python3.7-2024-10-28python3.6-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/uwsgi-nginx-flask:python3.7-2019-10-14 .
Image Docker avec UWSGI et NGINX pour les applications Web Flask dans Python exécutant dans un seul conteneur.
Cette image Docker vous permet de créer des applications Web Flask dans Python qui s'exécutent avec UWSGI et Nginx dans un seul conteneur.
La combinaison de UWSGI avec Nginx est un moyen courant de déployer des applications Web Python Flask.
Si vous commencez un nouveau projet, vous voudrez peut-être essayer Fastapi , que j'ai créé et où je passe la plupart de mon temps maintenant. Il n'a pas non plus besoin d'une image de base personnalisée, il y a des instructions dans les documents pour construire votre propre Dockerfile .
Github Repo : https://github.com/tiangolo/uwsgi-nginx-flask-docker
Image Docker Hub : https://hub.docker.com/r/tiangolo/uwsgi-nginx-flask/
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.12
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/uwsgi-nginx-flask:python3.12
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./app /appIl existe plusieurs balises d'image disponibles, mais pour les nouveaux projets, vous devez utiliser la dernière version disponible.
Cette image Docker est basée sur TiANGOLO / UWSGI-nginx . Cette image Docker a installé UWSGI et NGINX dans le même conteneur et a été fait pour être la base de cette image.
Dockerfile avec: FROM tiangolo/uwsgi-nginx-flask:python3.12
COPY ./app /appapp et entrez-ymain.py (il doit être nommé comme ça et doit être dans le répertoire de votre app ) avec: from flask import Flask
app = Flask ( __name__ )
@ app . route ( "/" )
def hello ():
return "Hello World from Flask"
if __name__ == "__main__" :
# Only for debugging while developing
app . run ( host = '0.0.0.0' , debug = True , port = 80 ) L'objet d'application principal doit être nommé app (dans le code) comme dans cet exemple.
Remarque : La section avec la fonction main() est à des fins de débogage. Pour en savoir plus, lisez les instructions avancées ci-dessous.
.
├── app
│ └── main.py
└── Dockerfile
Dockerfile , contenant votre répertoire app )docker build -t myimage .docker run -d --name mycontainer -p 80:80 myimage... et vous avez un serveur FLASK optimisé dans un conteneur Docker.
Vous devriez pouvoir le vérifier dans l'URL de votre conteneur Docker, par exemple: http://192.168.99.100 ou http://127.0.0.1
Si vous construisez des applications de frontend modernes (par exemple Vue, React, Angular), vous compileriez probablement une version moderne de JavaScript (ES2015, TypeScript, etc.) à une version moins moderne et plus compatible.
Si vous souhaitez servir votre code frontal (compilé) par le même conteneur Docker Backend (FLASK), vous devrez copier le code dans le conteneur après l'avoir compilé.
Cela signifie que vous auriez besoin que tous les outils de frontend soient installés sur la machine du bâtiment (ce pourrait être votre ordinateur, un serveur distant, etc.).
Cela signifie également que vous devrez, d'une manière ou d'une autre, toujours de compiler le code Frontend juste avant de construire l'image Docker.
Et cela pourrait également signifier que vous pourriez ensuite avoir à ajouter votre code de frontend compilé à votre référentiel git (j'espère que vous utilisez déjà Git, ou apprenez à utiliser git ).
L'ajout de votre code compilé à Git est une très mauvaise idée pour plusieurs raisons, certaines d'entre elles sont:
Pour ces raisons, il n'est pas recommandé de servir votre code frontal à partir du même conteneur Docker Backend (FLASK).
Il y a une bien meilleure alternative à servir votre code frontal à partir du même conteneur Docker Backend (FLASK).
Vous pouvez avoir un autre conteneur Docker avec tous les outils de frontend installés (Node.js, etc.) qui:
Pour apprendre les spécificités de ce processus pour le bâtiment Frontend dans Docker, vous pouvez lire:
Après avoir eu un récipient backend (flacon) et un conteneur frontal, vous devez les servir tous les deux.
Et vous voudrez peut-être les servir sous le même domaine, sous un chemin différent. Par exemple, l'application Backend (FLASK) au niveau du chemin /api et du frontend au chemin "Root" / .
Vous pouvez ensuite utiliser Trafik pour gérer cela.
Et il peut également générer automatiquement des certificats HTTPS pour votre application à l'aide de Let's Encrypt. Tout gratuitement, dans une configuration très facile.
Si vous souhaitez utiliser cette alternative, vérifiez les générateurs de projet ci-dessus, ils utilisent tous cette idée.
Dans ce scénario, vous auriez 3 conteneurs Docker:
Vous devriez être en mesure de suivre les mêmes instructions que dans la section " QuickStart " ci-dessus, avec quelques modifications mineures:
app/ répertoire, placez-le dans un répertoire app/app/ .__init__.py à l'intérieur de cette app/app/ répertoire.uwsgi.ini dans votre app/ répertoire (qui est copié sur /app/uwsgi.ini à l'intérieur du conteneur).uwsgi.ini , ajoutez: [uwsgi]
module = app.main
callable = app L'explication de l' uwsgi.ini est la suivante:
app.main . Ainsi, dans l' app du package ( /app/app ), obtenez le module main ( main.py ).app ( app = Flask(__name__) ).Votre structure de fichiers ressemblerait à:
.
├── app
│ ├── app
│ │ ├── __init__.py
│ │ ├── main.py
│ └── uwsgi.ini
└── Dockerfile
...au lieu de:
.
├── app
│ ├── main.py
└── Dockerfile
Si vous utilisez des fichiers statiques dans le même conteneur, assurez-vous que la variable d'environnement STATIC_PATH est définie en conséquence, par exemple pour modifier la valeur par défaut de /app/static à /app/app/static vous pouvez ajouter cette ligne à votre Dockerfile :
ENV STATIC_PATH /app/app/static... Après cela, tout devrait fonctionner comme prévu. Toutes les autres instructions s'appliqueraient normalement.
.
├── app
│ ├── app
│ │ ├── api
│ │ │ ├── api.py
│ │ │ ├── endpoints
│ │ │ │ ├── __init__.py
│ │ │ │ └── user.py
│ │ │ ├── __init__.py
│ │ │ └── utils.py
│ │ ├── core
│ │ │ ├── app_setup.py
│ │ │ ├── database.py
│ │ │ └── __init__.py
│ │ ├── __init__.py
│ │ ├── main.py
│ │ └── models
│ │ ├── __init__.py
│ │ └── user.py
│ └── uwsgi.ini
└── Dockerfile
Assurez-vous de suivre les documents officiels lors de l'importation de vos modules:
Par exemple, si vous êtes dans app/app/main.py et que vous souhaitez importer le module dans app/app/core/app_setup.py vous l'écririez comme:
from . core import app_setupou
from app . core import app_setupapp/app/api/endpoints/user.py et que vous souhaitez importer l'objet users à partir de app/app/core/database.py vous l'écririez comme: from ... core . database import usersou
from app . core . database import users Vous pouvez personnaliser plusieurs choses en utilisant des variables d'environnement.
index.html directementAVIS : Cette technique est obsolète, car elle peut créer plusieurs problèmes avec les cadres frontaux modernes. Pour les détails et de meilleures alternatives, lisez la section ci-dessus.
Définition de la variable d'environnement STATIC_INDEX pour être 1 vous pouvez configurer nginx pour servir le fichier dans l'URL /static/index.html lorsqu'il est demandé pour / .
Cela améliorerait la vitesse car cela n'impliquerait pas UWSGI ni Python. Nginx servirait directement le fichier. Pour en savoir plus, suivez la section ci-dessus " QuickStart pour les spas ".
Par exemple, pour l'activer, vous pouvez l'ajouter à votre Dockerfile :
ENV STATIC_INDEX 1Par défaut, l'image commence par 2 processus UWSGI en cours d'exécution. Lorsque le serveur connaît une charge élevée, il crée jusqu'à 16 processus UWSGI pour le gérer à la demande.
Si vous devez configurer ces nombres, vous pouvez utiliser des variables d'environnement.
Le numéro de départ des processus UWSGI est contrôlé par la variable UWSGI_CHEAPER , par défaut définie sur 2 .
Le nombre maximum de processus UWSGI est contrôlé par la variable UWSGI_PROCESSES , par défaut définie sur 16 .
Sachez que UWSGI_CHEAPER doit être inférieur à UWSGI_PROCESSES .
Donc, si, par exemple, vous devez commencer avec 4 processus et passer à un maximum de 64, votre Dockerfile pourrait ressembler:
FROM tiangolo/uwsgi-nginx-flask:python3.12
ENV UWSGI_CHEAPER 4
ENV UWSGI_PROCESSES 64
COPY ./app /app Vous pouvez définir une taille de fichier de téléchargement maximale personnalisée à l'aide d'une variable d'environnement NGINX_MAX_UPLOAD , par défaut, il a une valeur de 0 , qui permet des tailles de fichiers de téléchargement illimitées. Cela diffère de la valeur par défaut de Nginx de 1 Mo. Il est configuré de cette façon car c'est l'expérience la plus simple qu'un développeur inexpérimenté dans Nginx s'attendrait.
Par exemple, pour avoir une taille de fichier de téléchargement maximale de 1 Mo (par défaut de Nginx), ajoutez une ligne dans votre Dockerfile avec:
ENV NGINX_MAX_UPLOAD 1mPar défaut, le conteneur fabriqué à partir de cette image écoutera sur le port 80.
Pour modifier ce comportement, définissez la variable d'environnement LISTEN_PORT . Vous devrez peut-être également créer l'instruction EXPOSE Docker respective.
Vous pouvez le faire dans votre Dockerfile , cela ressemblerait à quelque chose:
FROM tiangolo/uwsgi-nginx-flask:python3.12
ENV LISTEN_PORT 8080
EXPOSE 8080
COPY ./app /appuwsgi.ini personnalisées Il y a un fichier par défaut dans /app/uwsgi.ini avec des configurations spécifiques à l'application (en plus des configurations globales uwsgi ).
Il contient seulement:
[uwsgi]
module = main
callable = appmodule = main fait référence au fichier main.pycallable = app se réfère à la "application" Flask , dans l' app variable. Vous pouvez personnaliser uwsgi en remplaçant ce fichier par le vôtre, y compris toutes vos configurations.
Par exemple, pour étendre le par défaut ci-dessus et activer les threads, vous pouvez avoir un fichier:
[uwsgi]
module = main
callable = app
enable-threads = trueuwsgi.ini personnalisé Vous pouvez remplacer où l'image doit rechercher le fichier d'application uwsgi.ini à l'aide de la variable d'environnement UWSGI_INI .
Avec cela, vous pouvez modifier le répertoire par défaut de votre application de /app à autre chose, comme /application .
Par exemple, pour faire en sorte que l'image utilise le fichier dans /application/uwsgi.ini , vous pouvez l'ajouter à votre Dockerfile :
ENV UWSGI_INI /application/uwsgi.ini
COPY ./application /application
WORKDIR /application Remarque : Le WORKDIR est important, sinon UWSGI essaiera d'exécuter l'application dans /app .
Remarque : vous devrez également configurer le chemin des fichiers static , lire ci-dessous.
./static/ Vous pouvez faire en sorte que Nginx utilise un chemin de répertoire personnalisé avec les fichiers pour servir directement (sans impliquer UWSGI) avec la variable d'environnement STATIC_PATH .
Par exemple, pour que nginx sert le contenu statique à l'aide des fichiers dans /app/custom_static/ vous pouvez l'ajouter à votre Dockerfile :
ENV STATIC_PATH /app/custom_static Ensuite, lorsque le navigateur a demandé un fichier dans, par exemple, http://example.com/static/index.html, Nginx répondrait directement à l'aide d'un fichier dans le path /app/custom_static/index.html .
Remarque : vous devrez également configurer Flask pour l'utiliser comme répertoire static .
Comme autre exemple, si vous deviez mettre votre code d'application dans un autre répertoire, vous pouvez configurer Nginx pour servir ces fichiers statiques de ce répertoire différent.
Si vous aviez besoin d'avoir vos fichiers statiques dans /application/static/ vous pouvez l'ajouter à votre Dockerfile :
ENV STATIC_PATH /application/static/static Vous pouvez également faire servir les fichiers statiques dans une URL différente, pour cela, vous pouvez utiliser la variable d'environnement STATIC_URL .
Par exemple, si vous vouliez modifier l'URL /static en /content vous pouvez l'ajouter à votre Dockerfile :
ENV STATIC_URL /content Ensuite, lorsque le navigateur a demandé un fichier dans, par exemple, http://example.com/content/index.html, Nginx répondrait directement à l'aide d'un fichier dans le path /app/static/index.html .
/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 Remarque : L'image utilise source pour exécuter le script, donc par exemple, les variables d'environnement persisteraient. Si vous ne comprenez pas la phrase précédente, vous n'en avez probablement pas besoin.
Par défaut, Nginx commencera un "processus de travail".
Si vous souhaitez définir un autre nombre de processus de travail Nginx, vous pouvez utiliser la variable d'environnement NGINX_WORKER_PROCESSES .
Vous pouvez utiliser un numéro unique spécifique, par exemple:
ENV NGINX_WORKER_PROCESSES 2 Ou vous pouvez le définir sur le mot-clé auto et il essaiera de détecter automatiquement le nombre de processeurs disponibles et de l'utiliser pour le nombre de travailleurs.
Par exemple, en utilisant auto , votre docker peut ressembler:
FROM tiangolo/uwsgi-nginx-flask:python3.12
ENV NGINX_WORKER_PROCESSES auto
COPY ./app /appPar défaut, Nginx commencera par une limite maximale de 1024 connexions par travailleur.
Si vous souhaitez définir un numéro différent, vous pouvez utiliser la variable d'environnement NGINX_WORKER_CONNECTIONS , par exemple:
ENV NGINX_WORKER_CONNECTIONS 2048Il ne peut pas dépasser la limite actuelle du nombre maximum de fichiers ouverts. Voyez comment le configurer dans la section suivante.
Les connexions numériques par travailleur Nginx ne peuvent pas dépasser la limite du nombre maximum de fichiers ouverts.
Vous pouvez modifier la limite des fichiers ouverts avec la variable d'environnement NGINX_WORKER_OPEN_FILES , par exemple:
ENV NGINX_WORKER_OPEN_FILES 2048 Si vous avez besoin de configurer Nginx davantage, vous pouvez ajouter *.conf Files à /etc/nginx/conf.d/ dans votre Dockerfile .
Gardez simplement à l'esprit que les configurations par défaut sont créées lors du démarrage dans un fichier à /etc/nginx/conf.d/nginx.conf et /etc/nginx/conf.d/upload.conf . Vous ne devriez donc pas les écraser. Vous devez nommer votre fichier *.conf avec quelque chose de différent de nginx.conf ou upload.conf , par exemple: custom.conf .
Remarque : Si vous personnalisez Nginx, peut-être en copie des configurations à partir d'un blog ou d'une réponse StackOverflow, gardez à l'esprit que vous devez probablement utiliser les configurations spécifiques à UWSGI, au lieu de celles des autres modules, comme par exemple, ngx_http_fastcgi_module .
Si vous avez besoin de configurer Nginx encore plus loin, dépassant complètement les valeurs par défaut, vous pouvez ajouter une configuration Nginx personnalisée à /app/nginx.conf .
Il sera copié sur /etc/nginx/nginx.conf et utilisé à la place de celui généré.
Gardez à l'esprit que, dans ce cas, cette image ne générera aucune des configurations Nginx, elle ne copiera et n'utilisera que votre fichier de configuration.
Cela signifie que toutes les variables d'environnement décrites ci-dessus qui sont spécifiques à Nginx ne seront pas utilisées.
Cela signifie également qu'il n'utilisera pas de configurations supplémentaires à partir de fichiers dans /etc/nginx/conf.d/*.conf , sauf si vous avez explicitement une section dans votre fichier personnalisé /app/nginx.conf avec:
include /etc/nginx/conf.d/*.conf;
Si vous souhaitez ajouter un fichier personnalisé /app/nginx.conf mais ne savez pas par où commencer, vous pouvez utiliser le nginx.conf utilisé pour les tests et le personnaliser ou le modifier davantage.
La combinaison de UWSGI avec Nginx est un moyen courant de déployer des applications Web Python Flask.
À peu près:
Nginx est un serveur Web, il s'occupe des connexions HTTP et peut également servir les fichiers statiques directement et plus efficacement.
UWSGI est un serveur d'applications, c'est ce qui exécute votre code Python et il parle avec Nginx.
Votre code Python a l'application Web Flask réelle et est exécutée par UWSGI.
L'image Tiangolo / UWSGI-nginx tire parti des images Docker minces et optimisées déjà existantes (basées sur Debian comme recommandé par Docker) et implémente plusieurs des meilleures pratiques de Docker.
Il utilise l'image officielle Python Docker, installe UWSGI et en plus de cela (avec le moins de modifications) ajoute l'image Nginx officielle.
Et il contrôle tous ces processus avec SuperVisord.
L'image (et les balises) créée par ce dépôt est basée sur l'image tiangolo / uwsgi-nginx . Cette image ajoute un ballon et des paramètres sensibles par-dessus.
Si vous suivez les instructions et gardez le répertoire /app racine dans votre conteneur, avec un fichier nommé main.py et un objet Flask nommé app , il devrait "simplement fonctionner".
Il y a déjà un fichier uwsgi.ini dans le répertoire /app avec les configurations UWSGI pour qu'il "fonctionne juste". Et tous les autres paramètres requis sont dans un autre fichier uwsgi.ini dans l'image, à l'intérieur /etc/uwsgi/ .
Si vous avez besoin de modifier le nom du fichier principal ou l'objet principal FLASK, vous devrez fournir votre propre fichier uwsgi.ini . Vous pouvez utiliser celui de ce dépôt comme un modèle pour commencer (et vous ne devriez changer que les 2 lignes correspondantes).
Vous pouvez avoir un répertoire A /app/static et ces fichiers seront significativement desservis par Nginx (sans passer par votre code FLASK ou même UWSGI), il est déjà configuré pour vous. Mais vous pouvez le configurer davantage en utilisant des variables d'environnement (lire ci-dessus).
SuperVisord s'occupe d'exécuter UWSGI avec le fichier uwsgi.ini dans /app Fichier (y compris également le fichier dans /etc/uwsgi/uwsgi.ini ) et de démarrer Nginx.
Il y a la règle de base selon laquelle vous devriez avoir "un processus par conteneur".
Cela aide, par exemple, à isoler une application et sa base de données dans différents conteneurs.
Mais si vous voulez avoir une approche "micro-services", vous voudrez peut-être avoir plus d'un processus dans un conteneur s'ils sont tous liés au même "service", et vous voudrez peut-être inclure votre code FLASK, UWSGI et NGINX dans le même conteneur (et peut-être exécuter un autre conteneur avec votre base de données).
C'est l'approche adoptée dans cette image.
Cette image (et les balises) ont des fichiers par défaut, donc si vous l'exécutez seul (pas comme l'image de base de votre propre projet), vous verrez une application Web par défaut "Hello World".
Lorsque vous créez un Dockerfile avec une COPY ./app /app vous remplacez ces fichiers par défaut par votre code d'application.
Le fichier par défaut principal est uniquement dans /app/main.py . Et dans le cas des balises avec -index , également dans /app/static/index.html .
Mais ces fichiers rendent un texte "(par défaut)" dans la page Web servie, afin que vous puissiez vérifier si vous voyez le code par défaut ou votre propre code dépassant la valeur par défaut.
Votre code d'application doit être dans le répertoire du conteneur /app , il doit avoir un fichier main.py et que le fichier main.py devrait avoir une app d'objet Flask.
Si vous suivez les instructions ci-dessus ou utilisez l'un des modèles d'exemples téléchargeables, vous devez être OK.
Il existe également un fichier A /app/uwsgi.ini à l'intérieur des images avec les paramètres par défaut pour UWSGI.
Les exemples téléchargeables incluent une copie du même fichier uwsgi.ini à des fins de débogage. Pour en savoir plus, lisez les « instructions de développement avancées » ci-dessous.
Pendant le développement, vous voudrez peut-être faire de votre répertoire de code un volume dans votre conteneur Docker.
Avec cela, vos fichiers auraient (temporairement) mis à jour chaque fois que vous les modifiez, sans avoir besoin de créer à nouveau votre conteneur.
Pour ce faire, vous pouvez utiliser la commande pwd (Imprimer le répertoire de travail) à l'intérieur de votre docker run et de l'indicateur -v pour les volumes.
Avec cela, vous pouvez cartographier votre répertoire ./app dans le répertoire de votre conteneur /app .
Mais d'abord, comme vous remplacerez complètement le répertoire /app dans votre conteneur (et tout son contenu), vous devrez avoir un fichier uwsgi.ini dans votre répertoire ./app avec:
[uwsgi]
module = main
callable = appEt puis vous pouvez faire le mappage du volume Docker.
Remarque : un fichier uwsgi.ini est inclus dans les exemples téléchargeables.
Dockerfile et votre répertoire ./app )uwsgi.ini dans votre répertoire ./appdocker build -t myimage ../app ) dans le répertoire de votre conteneur /app : docker run -d --name mycontainer -p 80:80 -v $( pwd ) /app:/app myimage Si vous accédez à votre URL de conteneur Docker, vous devriez voir votre application, et vous devriez pouvoir modifier des fichiers dans ./app/static/ et voir ces modifications reflétées dans votre navigateur simplement en rechargeant.
... Mais, comme UWSGI charge votre application Web Python Flask entière une fois qu'elle commence, vous ne pourrez pas modifier votre code Python Flask et voir les modifications reflétées.
Pour pouvoir (temporairement) déboguer votre code Python Flask en direct, vous pouvez exécuter votre conteneur en remplaçant la commande par défaut (qui démarre SuperVisord qui démarre à son tour UWSGI et NGINX) et exécuter votre application directement avec python , en mode de débogage, en utilisant la commande flask avec ses variables d'environnement.
Ainsi, avec toutes les modifications ci-dessus et faisant fonctionner votre application directement avec flask , la commande Docker finale serait:
docker run -d --name mycontainer -p 80:80 -v $( pwd ) /app:/app -e FLASK_APP=main.py -e FLASK_DEBUG=1 myimage flask run --host=0.0.0.0 --port=80 Ou dans le cas d'un projet de package, vous définissez FLASK_APP=main/main.py :
docker run -d --name mycontainer -p 80:80 -v $( pwd ) /app:/app -e FLASK_APP=main/main.py -e FLASK_DEBUG=1 myimage flask run --host=0.0.0.0 --port=80Vous pouvez maintenant modifier votre code de flacon dans votre machine locale et une fois que vous avez actualisé votre navigateur, vous verrez les modifications en direct.
N'oubliez pas que vous devez l'utiliser uniquement pour le débogage et le développement, pour le déploiement de la production, vous ne devez pas monter de volumes et vous devriez laisser démarrer SuperVisord et le laisser démarrer UWSGI et Nginx (ce qui se passe par défaut).
Une alternative pour ces dernières étapes pour fonctionner lorsque vous n'avez pas de package, mais juste une structure plate avec des fichiers uniques (modules), votre code Python Flask pourrait avoir cette section avec:
if __name__ == "__main__" :
# Only for debugging while developing
app . run ( host = '0.0.0.0' , debug = True , port = 80 ) ... et vous pourriez l'exécuter avec python main.py Mais cela ne fonctionnera que lorsque vous n'utilisez pas de structure de package et que vous ne prévoyez pas de le faire plus tard. Dans ce cas spécifique, si vous n'avez pas ajouté le bloc de code ci-dessus, votre application n'écouterait que localhost (à l'intérieur du conteneur), dans un autre port (5000) et non en mode débogage.
De plus, si vous souhaitez faire le même débogage en direct à l'aide de la variable d'environnement STATIC_INDEX=1 (pour servir /app/static/index.html directement lorsqu'il est demandé pour / ) votre Nginx ne le servira pas directement en fonction (seul votre application Python Flask en mode débogage fonctionnera).
from flask import Flask , send_fileet
@ app . route ( '/' )
def route_root ():
index_path = os . path . join ( app . static_folder , 'index.html' )
return send_file ( index_path ) ... Cela garantit que votre application sert également le fichier /app/static/index.html lorsqu'il est demandé pour / . Ou si vous utilisez une structure de package, le fichier /app/main/static/index.html .
Et si vous utilisez un framework SPA, pour lui permettre de gérer les URL dans le navigateur, votre code Python Flask devrait avoir la section avec:
# Everything not declared before (not a Flask route / API endpoint)...
@ app . route ( '/<path:path>' )
def route_frontend ( path ):
# ...could be a static file needed by the front end that
# doesn't use the `static` path (like in `<script src="bundle.js">`)
file_path = os . path . join ( app . static_folder , path )
if os . path . isfile ( file_path ):
return send_file ( file_path )
# ...or should be handled by the SPA's "router" in front end
else :
index_path = os . path . join ( app . static_folder , 'index.html' )
return send_file ( index_path ) ... Cela fait que FLASK envoie tous les fichiers CSS, JavaScript et image lorsqu'ils sont demandés dans l'URL racine ( / ), mais s'assure également que votre spa frontal gère toutes les autres URL qui ne sont pas définies dans votre application Flask.
C'est ainsi qu'il est écrit dans le tutoriel ci-dessus et est inclus dans les exemples téléchargeables.
Si vous suivez les instructions ci-dessus, il est probable qu'à un moment donné, vous rédigerez du code qui cassera votre serveur de débogage FLASK et qu'il se bloquera.
Et comme le seul processus en cours d'exécution était votre serveur de débogage, qui est maintenant arrêté, votre conteneur s'arrêtera.
Ensuite, vous devrez recommencer votre conteneur après avoir corrigé votre code et vous ne verrez pas très facilement quelle est l'erreur qui écrase votre serveur.
Ainsi, pendant le développement, vous pouvez faire ce qui suit (c'est ce que je fais normalement, bien que je le fasse avec Docker Compose, comme dans l'exemple de projets):
docker run -d --name mycontainer -p 80:80 -v $( pwd ) /app:/app -e FLASK_APP=main.py -e FLASK_DEBUG=1 myimage bash -c " while true ; do sleep 10 ; done "FLASK_APP=main/main.py : docker run -d --name mycontainer -p 80:80 -v $( pwd ) /app:/app -e FLASK_APP=main/main.py -e FLASK_DEBUG=1 myimage bash -c " while true ; do sleep 10 ; done "docker exec -it mycontainer bash Vous serez désormais à l'intérieur de votre conteneur dans le répertoire /app .
flask run --host=0.0.0.0 --port=80Vous verrez le démarrage de votre serveur de débogage FLASK, vous verrez comment il envoie des réponses à chaque demande, vous verrez les erreurs lancées lorsque vous cassez votre code et comment ils arrêtent votre serveur, et vous pourrez le redémarrer très rapidement, en exécutant à nouveau la commande à nouveau.
Toutes les balises d'image, les configurations, les variables d'environnement et les options d'application sont testées.
issue-manager.yml . PR # 385 par @tiangolo.latest-changes . PR # 360 par @tiangolo.latest-changes.yml . PR # 348 par @alejsdev.README.md . PR # 346 par @alejsdev. Faits saillants de cette version:
python3.6-2022-11-25 et python2.7-2022-11-25 .1.17.10 .3.11 .-index sufix tags.-index (use ENV STATIC_INDEX 1 instead).2020-05-04 .tiangolo/uwsgi-nginx-flask:python3.8-2019-10-14 . PR #154./start.sh and /app/prestart.sh functionality to parent image. PR #134.2019-02-02:
uwsgi-nginx and PR #121./app/nginx.conf file that overrides the generated one. PR #51 in the parent image uwsgi-nginx and PR #122.2019-01-01:
2018-12-29:
2018-11-23:
2018-09-22:
2018-06-22:
NGINX_WORKER_CONNECTIONS to set the maximum number of Nginx worker connections and NGINX_WORKER_OPEN_FILES to set the maximum number of open files. Thanks to ronlut in this PR.2018-06-22:
Improvements from parent image:
Make uWSGI require an app to run, instead of going in "full dynamic mode" while there was an error. Supervisord doesn't terminate itself but tries to restart uWSGI and shows the errors. Uses need-app as suggested by luckydonald in this comment.
Correctly handled graceful shutdown of uWSGI and Nginx. Thanks to desaintmartin in this PR.
2018-02-04:
It's now possible to set the number of Nginx worker processes with the environment variable NGINX_WORKER_PROCESSES . Thanks to naktinis in this PR.
2018-01-14:
python2.7-alpine3.7 and python3.6-alpine3.7 .2017-12-10:
/app/prestart.sh script to run arbitrary code before starting the app (for example, Alembic - SQLAlchemy migrations). The documentation for the /app/prestart.sh is in the main README./app is part of the PYTHONPATH environment variable. That allows global imports from several places, easier Alembic integration, etc. 2017-12-08: Now you can configure which port the container should listen on, using the environment variable LISTEN_PORT thanks to tmshn in this PR.
2017-09-10: Updated examples and sample project to work with SPAs even when structuring the app as a package (with subdirectories).
2017-09-02:
flask run commands, that allows running a package application while developing more easily.2017-08-10: Many changes:
python3.6 , python3.6-index , python.3.5 , python3.5-index , python2.7 and python2.7-index . All the other images are deprecated in favor is this ones.latest will point to Python 3.6 and the other tags will be removed.tiangolo/uwsgi-nginx that improved this image too.index.html directly: STATIC_INDEXNGINX_MAX_UPLOADuwsgi.ini file (that allows using a custom directory different than /app ): UWSGI_INI (using the ideas by @bercikr in #5 )../static/ path: STATIC_PATH/static/ URL: STATIC_URLDockerfile with: FROM tiangolo/uwsgi-nginx-flask:python3.6
COPY ./app /appand then customize with environment variables.
This project is licensed under the terms of the Apache license.