Dockerfilepython3.12 , latest (Dockerfile)python3.11 , (Dockerfile)python3.10 (Dockerfile)python3.9 , (Dockerfile) Essas tags não são mais suportadas ou mantidas, elas são removidas do repositório do GitHub, mas as últimas versões pressionadas ainda podem estar disponíveis no Docker Hub se alguém os estiver puxando:
python3.8python3.8-alpinepython3.7python3.6python2.7As tags de última data para essas versões são:
python3.8-2024-10-28python3.8-alpine-2024-03-11python3.7-2024-10-28python3.6-2022-11-25python2.7-2022-11-25 Nota : Existem tags para cada data de construção. Se você precisar "fixar" a versão da imagem do Docker que você usa, poderá selecionar uma dessas tags. Por exemplo, tiangolo/uwsgi-nginx-flask:python3.7-2019-10-14 .
Imagem do docker com aplicativos UWSGI e NGINX para Flask Web em Python em execução em um único contêiner.
Esta imagem do Docker permite criar aplicativos da Web Flask no Python que são executados com UWSGI e NGINX em um único contêiner.
A combinação de UWSGI com Nginx é uma maneira comum de implantar aplicativos da web do Flask Python.
Se você está iniciando um novo projeto, pode querer experimentar o FASTAPI , que eu criei, e onde passo a maior parte do tempo agora. Ele também não precisa de uma imagem base personalizada, há instruções nos documentos para construir seu próprio Dockerfile .
Repo Github : https://github.com/tiangolo/uwsgi-nginx-flask-docker
Docker Hub Imagem : https://hub.docker.com/r/tiangolo/uwsgi-nginx-flask/
Você provavelmente está usando Kubernetes ou ferramentas semelhantes. Nesse caso, você provavelmente não precisa desta imagem (ou de qualquer outra imagem base semelhante ). Você provavelmente é melhor construir uma imagem do Docker a partir do zero .
Se você possui um cluster de máquinas com Kubernetes , modo de enxame do Docker, Nomad ou outro sistema complexo semelhante para gerenciar contêineres distribuídos em várias máquinas, provavelmente desejará lidar com a replicação no nível do cluster, em vez de usar um gerenciador de processos em cada contêiner que inicie os processos de vários trabalhadores , o que é a imagem do Docker.
Nesses casos (por exemplo, usando Kubernetes), você provavelmente gostaria de criar uma imagem do Docker a partir do zero , instalando suas dependências e executando um único processo em vez dessa imagem.
Por exemplo, usando o Gunicorn, você pode ter um app/gunicorn_conf.py com:
# Gunicorn config variables
loglevel = "info"
errorlog = "-" # stderr
accesslog = "-" # stdout
worker_tmp_dir = "/dev/shm"
graceful_timeout = 120
timeout = 120
keepalive = 5
threads = 3 E então você pode ter um Dockerfile com:
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" ]Você pode ler mais sobre essas idéias na documentação do FASTAPI sobre: FASTAPI em contêineres - Docker, pois as mesmas idéias se aplicariam a outros aplicativos da Web em contêineres.
Você pode querer um gerenciador de processos executando vários processos de trabalhador no contêiner se o seu aplicativo for simples o suficiente para que você não precise (pelo menos ainda não) para ajustar muito o número de processos e você pode usar um padrão automatizado e está executando-o em um único servidor , não em um cluster.
Você pode estar implantando para um único servidor (não um cluster) com o Docker Compose , para não ter uma maneira fácil de gerenciar a replicação de contêineres (com o Docker Compose) enquanto preservava a rede compartilhada e o balanceamento de carga .
Em seguida, você pode querer ter um único contêiner com um gerenciador de processos iniciando vários processos de trabalhador dentro, como essa imagem do Docker.
Você também pode ter outros motivos que facilitariam a ter um único contêiner com vários processos, em vez de ter vários contêineres com um único processo em cada um deles.
Por exemplo (dependendo da sua configuração), você pode ter alguma ferramenta, como um exportador do Prometheus no mesmo contêiner que deve ter acesso a cada uma das solicitações que vêm.
Nesse caso, se você tivesse vários contêineres , por padrão, quando o Prometheus chegasse a ler as métricas , ele receberia um único contêiner de cada vez (para o contêiner que lidava com essa solicitação específica), em vez de obter as métricas acumuladas para todos os contêineres replicados.
Então, nesse caso, pode ser mais simples ter um contêiner com vários processos e uma ferramenta local (por exemplo, um exportador de Prometheus) no mesmo contêiner coletando métricas de Prometheus para todos os processos internos e expondo essas métricas nesse contêiner único.
Leia mais sobre tudo na documentação do FASTAPI sobre: FASTAPI em contêineres - Docker, pois os mesmos conceitos se aplicam a outros aplicativos da Web em contêineres.
Você não precisa clonar este repo.
Você pode usar esta imagem como uma imagem base para outras imagens.
Supondo que você tenha um arquivo requirements.txt , você pode ter um Dockerfile como este:
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 /appExistem várias tags de imagem disponíveis, mas para novos projetos, você deve usar a versão mais recente disponível.
Esta imagem do docker é baseada em tiangolo/uwsgi-nginx . Essa imagem do Docker possui UWSGI e Nginx instalados no mesmo contêiner e foi feito para ser a base desta imagem.
Dockerfile com: FROM tiangolo/uwsgi-nginx-flask:python3.12
COPY ./app /appapp e entre nelemain.py (ele deve ser nomeado assim e deve estar no seu diretório app ) com: 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 ) O objeto principal do aplicativo deve ser nomeado app (no código) como neste exemplo.
Nota : A seção com a função main() é para fins de depuração. Para saber mais, leia as instruções avançadas abaixo.
.
├── app
│ └── main.py
└── Dockerfile
Dockerfile , contendo seu diretório app )docker build -t myimage .docker run -d --name mycontainer -p 80:80 myimage... e você tem um servidor de frasco otimizado em um contêiner do Docker.
Você deve verificá -lo no URL do seu contêiner do Docker, por exemplo: http://192.168.99.100 ou http://127.0.0.1
Se você estiver criando aplicações modernas de front -end (por exemplo, Vue, React, Angular), provavelmente compilaria uma versão moderna do JavaScript (ES2015, TypeScript, etc) a uma versão menos moderna e mais compatível.
Se você deseja servir o seu código de front -end (compilado) pelo mesmo contêiner de back -end (frasco), precisaria copiar o código para o contêiner depois de compilá -lo.
Isso significa que você precisaria ter todas as ferramentas de front -end instaladas na máquina de construção (pode ser o seu computador, um servidor remoto etc.).
Isso também significa que você precisaria, de alguma forma, lembre -se sempre de compilar o código do front -end antes de criar a imagem do Docker.
E isso também pode significar que você pode ter que adicionar seu código de front -end compilado ao seu repositório git (espero que você já esteja usando o GIT ou aprendendo a usar git ).
Adicionar seu código compilado ao Git é uma péssima idéia por várias razões, algumas delas são:
Por esses motivos, não é recomendável que você sirva seu código de front -end do mesmo contêiner de back -end (frasco).
Há uma alternativa muito melhor para servir seu código de front -end do mesmo contêiner de back -end (frasco) do docker.
Você pode ter outro recipiente do docker com todas as ferramentas de front -end instaladas (node.js, etc) que:
Para aprender as especificidades desse processo para o edifício front -end em Docker, você pode ler:
Depois de ter um recipiente de back -end (frasco) e um recipiente de front -end, você precisa servir os dois.
E você pode querer servi -los sob o mesmo domínio, sob um caminho diferente. Por exemplo, o aplicativo de back -end (Flask) no caminho /api e na front -end no caminho "raiz" / .
Você pode usar o Traefik para lidar com isso.
E também pode gerar automaticamente certificados HTTPS para o seu aplicativo usando o Let's Encrypt. Tudo de graça, em uma configuração muito fácil.
Se você deseja usar essa alternativa, verifique os geradores do projeto acima, todos eles usam essa ideia.
Nesse cenário, você teria 3 contêineres do Docker:
Você deve seguir as mesmas instruções da seção " QuickStart " acima, com algumas pequenas modificações:
app/ diretório, coloque -o em um app/app/ .__init__.py dentro desse app/app/ diretório.uwsgi.ini dentro do seu app/ diretório (que é copiado para /app/uwsgi.ini dentro do contêiner).uwsgi.ini , adicione: [uwsgi]
module = app.main
callable = app A explicação do uwsgi.ini é a seguinte:
app.main . Portanto, no app do pacote ( /app/app ), obtenha o módulo main ( main.py ).app ( app = Flask(__name__) ).Sua estrutura de arquivos seria:
.
├── app
│ ├── app
│ │ ├── __init__.py
│ │ ├── main.py
│ └── uwsgi.ini
└── Dockerfile
...em vez de:
.
├── app
│ ├── main.py
└── Dockerfile
Se você estiver usando arquivos estáticos no mesmo contêiner, verifique se a variável de ambiente STATIC_PATH está definida de acordo, por exemplo, para alterar o valor padrão de /app/static para /app/app/static você poderá adicionar esta linha ao seu Dockerfile :
ENV STATIC_PATH /app/app/static... Depois disso, tudo deve funcionar conforme o esperado. Todas as outras instruções se aplicariam normalmente.
.
├── 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
Certifique -se de seguir os documentos oficiais enquanto importa seus módulos:
Por exemplo, se você estiver em app/app/main.py e deseja importar o módulo no app/app/core/app_setup.py você o escreveria como:
from . core import app_setupou
from app . core import app_setupapp/app/api/endpoints/user.py e deseja importar o objeto users do app/app/core/database.py você o escreveria como: from ... core . database import usersou
from app . core . database import users Você pode personalizar várias coisas usando variáveis de ambiente.
index.html diretamenteAVISO : Esta técnica está presa, pois pode criar vários problemas com as estruturas modernas de front -end. Para obter detalhes e melhores alternativas, leia a seção acima.
Definir a variável de ambiente STATIC_INDEX como 1 Você pode configurar o nginx para servir o arquivo no url /static/index.html quando solicitado para / .
Isso melhoraria a velocidade, pois não envolveria UWSGI nem Python. Nginx serviria o arquivo diretamente. Para saber mais, siga a seção acima " Quickstart for Spas ".
Por exemplo, para ativá -lo, você pode adicionar isso ao seu Dockerfile :
ENV STATIC_INDEX 1Por padrão, a imagem começa com 2 processos UWSGI em execução. Quando o servidor está passando por uma carga alta, ele cria até 16 processos UWSGI para lidar com isso sob demanda.
Se você precisar configurar esses números, poderá usar variáveis de ambiente.
O número inicial de processos UWSGI é controlado pela variável UWSGI_CHEAPER , por padrão definido como 2 .
O número máximo de processos UWSGI é controlado pela variável UWSGI_PROCESSES , por padrão definido como 16 .
Lembre -se de que UWSGI_CHEAPER deve ser menor que UWSGI_PROCESSES .
Então, se, por exemplo, você precisar começar com 4 processos e crescer no máximo 64, seu Dockerfile poderia parecer:
FROM tiangolo/uwsgi-nginx-flask:python3.12
ENV UWSGI_CHEAPER 4
ENV UWSGI_PROCESSES 64
COPY ./app /app Você pode definir um tamanho de arquivo de upload máximo personalizado usando uma variável de ambiente NGINX_MAX_UPLOAD , por padrão, ele possui um valor 0 , que permite tamanhos de arquivo de upload ilimitados. Isso difere do valor padrão do Nginx de 1 MB. Ele está configurado dessa maneira, porque essa é a experiência mais simples que um desenvolvedor inexperiente no Nginx esperaria.
Por exemplo, para ter um tamanho de arquivo de upload máximo de 1 MB (padrão do nginx), adicione uma linha no seu Dockerfile com:
ENV NGINX_MAX_UPLOAD 1mPor padrão, o contêiner feito a partir desta imagem ouvirá na porta 80.
Para alterar esse comportamento, defina a variável de ambiente LISTEN_PORT . Você também pode precisar criar as respectivas instruções EXPOSE Docker.
Você pode fazer isso no seu Dockerfile , seria algo como:
FROM tiangolo/uwsgi-nginx-flask:python3.12
ENV LISTEN_PORT 8080
EXPOSE 8080
COPY ./app /appuwsgi.ini Existe um arquivo padrão em /app/uwsgi.ini com configurações específicas do aplicativo (no topo das configurações globais uwsgi ).
Ele só contém:
[uwsgi]
module = main
callable = appmodule = main refere -se ao arquivo main.pycallable = app refere -se ao Flask "Aplicativo", no app variável. Você pode personalizar uwsgi substituindo esse arquivo por seu próprio, incluindo todas as suas configurações.
Por exemplo, para estender o padrão acima e habilitar threads, você pode ter um arquivo:
[uwsgi]
module = main
callable = app
enable-threads = trueuwsgi.ini Você pode substituir onde a imagem deve procurar o arquivo app uwsgi.ini usando a variável de ambiente UWSGI_INI .
Com isso, você pode alterar o diretório padrão do seu aplicativo de /app para outra coisa, como /application .
Por exemplo, para fazer a imagem usar o arquivo em /application/uwsgi.ini , você pode adicioná -lo ao seu Dockerfile :
ENV UWSGI_INI /application/uwsgi.ini
COPY ./application /application
WORKDIR /application Nota : O WORKDIR é importante, caso contrário, o UWSGI tentará executar o aplicativo em /app .
NOTA : Você também precisaria configurar o caminho dos arquivos static , lido abaixo.
./static/ Você pode fazer com que o NGINX use um caminho de diretório personalizado com os arquivos para servir diretamente (sem envolver o UWSGI) com a variável de ambiente STATIC_PATH .
Por exemplo, para fazer o Nginx servir o conteúdo estático usando os arquivos em /app/custom_static/ você pode adicioná -lo ao seu Dockerfile :
ENV STATIC_PATH /app/custom_static Então, quando o navegador solicitou um arquivo, por exemplo, http://example.com/static/index.html, o nginx responderia diretamente usando um arquivo no caminho /app/custom_static/index.html .
Nota : você também precisaria configurar o Flask para usá -lo como seu diretório static .
Como outro exemplo, se você precisar colocar seu código de aplicativo em um diretório diferente, poderá configurar o NGINX para atender a esses arquivos estáticos desse diretório diferente.
Se você precisava ter seus arquivos estáticos em /application/static/ poderá adicioná -lo ao seu Dockerfile :
ENV STATIC_PATH /application/static/static Você também pode fazer com que o NGINX sirva os arquivos estáticos em um URL diferente, para isso, você pode usar a variável de ambiente STATIC_URL .
Por exemplo, se você quiser alterar o URL /static para /content poderá adicioná -lo ao seu Dockerfile :
ENV STATIC_URL /content Então, quando o navegador solicitou um arquivo, por exemplo, http://example.com/content/index.html, o nginx responderia diretamente usando um arquivo no caminho /app/static/index.html .
/app/prestart.sh Se você precisar executar qualquer coisa antes de iniciar o aplicativo, poderá adicionar um arquivo prestart.sh ao diretório /app . A imagem será detectada e executada automaticamente antes de iniciar tudo.
Por exemplo, se você deseja adicionar migrações SQL Alembic (com sqlalchemy), pode criar um arquivo ./app/prestart.sh no seu diretório de código (que será copiado pelo seu Dockerfile ) com:
#! /usr/bin/env bash
# Let the DB start
sleep 10 ;
# Run migrations
alembic upgrade head E esperaria 10 segundos para dar ao banco de dados algum tempo para iniciar e, em seguida, executar esse comando alembic .
Se você precisar executar um script python antes de iniciar o aplicativo, você pode fazer com que o arquivo /app/prestart.sh execute seu script python, com algo como:
#! /usr/bin/env bash
# Run custom Python script before starting
python /app/my_custom_prestart_script.py Nota : A imagem usa source para executar o script; portanto, por exemplo, as variáveis de ambiente persistiriam. Se você não entende a frase anterior, provavelmente não precisa dela.
Por padrão, o NGINX iniciará um "processo do trabalhador".
Se você deseja definir um número diferente de processos de trabalhador nginx, poderá usar a variável de ambiente NGINX_WORKER_PROCESSES .
Você pode usar um número único específico, por exemplo:
ENV NGINX_WORKER_PROCESSES 2 Ou você pode configurá-lo para a palavra-chave auto e ele tentará detectar automaticamente o número de CPUs disponíveis e usá-lo para o número de trabalhadores.
Por exemplo, usando auto , seu Dockerfile pode parecer:
FROM tiangolo/uwsgi-nginx-flask:python3.12
ENV NGINX_WORKER_PROCESSES auto
COPY ./app /appPor padrão, o NGINX começará com um limite máximo de 1024 conexões por trabalhador.
Se você deseja definir um número diferente, pode usar a variável de ambiente NGINX_WORKER_CONNECTIONS , por exemplo:
ENV NGINX_WORKER_CONNECTIONS 2048Não pode exceder o limite atual do número máximo de arquivos abertos. Veja como configurá -lo na próxima seção.
As conexões numéricas por trabalhador nginx não podem exceder o limite do número máximo de arquivos abertos.
Você pode alterar o limite de arquivos abertos com a variável de ambiente NGINX_WORKER_OPEN_FILES , por exemplo:
ENV NGINX_WORKER_OPEN_FILES 2048 Se você precisar configurar ainda mais o nginx, poderá adicionar arquivos *.conf a /etc/nginx/conf.d/ no seu Dockerfile .
Só tenho em mente que as configurações padrão são criadas durante a inicialização em um arquivo em /etc/nginx/conf.d/nginx.conf e /etc/nginx/conf.d/upload.conf . Então você não deve substituí -los. Você deve nomear seu arquivo *.conf com algo diferente de nginx.conf ou upload.conf , por exemplo: custom.conf .
NOTA : Se você estiver personalizando o NGINX, talvez copie as configurações de um blog ou uma ngx_http_fastcgi_module de StackOverflow, lembre -se de que provavelmente precisar
Se você precisar configurar ainda mais o Nginx, substituindo completamente os padrões, poderá adicionar uma configuração NGINX personalizada ao /app/nginx.conf .
Ele será copiado para /etc/nginx/nginx.conf e usado em vez do gerado.
Lembre -se de que, nesse caso, essa imagem não gera nenhuma das configurações do NGINX, ele apenas copiará e usará seu arquivo de configuração.
Isso significa que todas as variáveis de ambiente descritas acima que são específicas para o NGINX não serão usadas.
Isso também significa que não usará configurações adicionais de arquivos em /etc/nginx/conf.d/*.conf , a menos que você tenha explicitamente uma seção em seu arquivo personalizado /app/nginx.conf com:
include /etc/nginx/conf.d/*.conf;
Se você deseja adicionar um arquivo personalizado /app/nginx.conf mas não sabe de onde começar, você pode usar o nginx.conf usado para os testes e personalizá -lo ou modificá -lo ainda mais.
A combinação de UWSGI com Nginx é uma maneira comum de implantar aplicativos da web do Flask Python.
Aproximadamente:
O NGINX é um servidor da Web, cuida das conexões HTTP e também pode servir arquivos estáticos diretamente e com mais eficiência.
O UWSGI é um servidor de aplicativos, é isso que executa seu código Python e fala com o NGINX.
Seu código Python possui o aplicativo Web de Flask real e é executado pelo UWSGI.
A imagem Tiangolo/UWSGI-NGINX aproveita as imagens de Docker Slim e Otimizadas já existentes (baseadas no Debian, conforme recomendado pelo Docker) e implementa várias das melhores práticas do Docker.
Ele usa a imagem oficial do Python Docker, instala UWSGI e, além disso (com a menor quantidade de modificações), adiciona a imagem oficial do NGINX.
E controla todos esses processos com o supervisor.
A imagem (e as tags) criada por este repositório é baseada na imagem tiangolo/uwsgi-nginx . Esta imagem adiciona frasco e padrões sensíveis em cima.
Se você seguir as instruções e manter o diretório /app raiz em seu contêiner, com um arquivo chamado main.py e um objeto de frasco chamado app , ele deve "apenas trabalhar".
Já existe um arquivo uwsgi.ini no diretório /app com as configurações UWSGI para que "apenas trabalhe". E todos os outros parâmetros necessários estão em outro arquivo uwsgi.ini na imagem, dentro /etc/uwsgi/ .
Se você precisar alterar o nome principal do arquivo ou o objeto principal do Flask, precisará fornecer seu próprio arquivo uwsgi.ini . Você pode usar o nesse repo como modelo para começar (e você só teria que alterar as 2 linhas correspondentes).
Você pode ter um diretório /app/static e esses arquivos serão atendidos com eficiência diretamente pelo NGINX (sem passar pelo código do Flask ou mesmo UWSGI), ele já está configurado para você. Mas você pode configurá -lo ainda mais usando variáveis de ambiente (lido acima).
O Supervisord cuida da execução do UWSGI com o arquivo uwsgi.ini no arquivo /app (incluindo também o arquivo em /etc/uwsgi/uwsgi.ini ) e o início do nginx.
Existe a regra prática de que você deve ter "um processo por contêiner".
Isso ajuda, por exemplo, isolando um aplicativo e seu banco de dados em diferentes contêineres.
Mas se você deseja ter uma abordagem de "micro-serviços", poderá ter mais de um processo em um contêiner, se todos estiverem relacionados ao mesmo "serviço", e você pode incluir seu código de frasco, UWSGI e NGINX no mesmo contêiner (e talvez execute outro contêiner com seu banco de dados).
Essa é a abordagem adotada nesta imagem.
Esta imagem (e tags) possui alguns arquivos padrão; portanto, se você a executar por si só (não como a imagem base do seu próprio projeto), você verá um aplicativo padrão da web "Hello World".
Ao criar um Dockerfile com uma COPY ./app /app você substitui esses arquivos padrão pelo código do aplicativo.
O arquivo padrão principal é apenas em /app/main.py . E no caso das tags com -index , também em /app/static/index.html .
Mas esses arquivos renderizam um texto "(padrão)" na página da web servida, para que você possa verificar se estiver vendo o código padrão ou seu próprio código substituindo o padrão.
O código do seu aplicativo deve estar no diretório do contêiner /app , ele deve ter um arquivo main.py e que o arquivo main.py deve ter um app de objeto Flask.
Se você seguir as instruções acima ou usar um dos modelos de exemplo para download, você estará bem.
Há também o arquivo A /app/uwsgi.ini dentro das imagens com os parâmetros padrão do UWSGI.
Os exemplos para download incluem uma cópia do mesmo arquivo uwsgi.ini para fins de depuração. Para saber mais, leia as " instruções avançadas de desenvolvimento " abaixo.
Durante o desenvolvimento, você pode querer tornar seu diretório de código um volume no seu contêiner do Docker.
Com isso, você teria seus arquivos (temporariamente) atualizados toda vez que os modificam, sem precisar criar seu contêiner novamente.
Para fazer isso, você pode usar o comando pwd (imprimir diretório de trabalho) dentro do seu docker run e o sinalizador -v para volumes.
Com isso, você pode mapear seu diretório ./app para o diretório do seu contêiner /app .
Mas primeiro, como você substituirá completamente o diretório /app em seu contêiner (e todo o seu conteúdo), você precisará ter um arquivo uwsgi.ini no seu diretório ./app com:
[uwsgi]
module = main
callable = appE então você pode fazer o mapeamento do volume do Docker.
Nota : Um arquivo uwsgi.ini está incluído nos exemplos para download.
Dockerfile e seu diretório ./app )uwsgi.ini no seu diretório ./appdocker build -t myimage ../app ) para o diretório do seu contêiner /app : docker run -d --name mycontainer -p 80:80 -v $( pwd ) /app:/app myimage Se você for ao URL do contêiner do Docker, verá seu aplicativo e poderá modificar arquivos em ./app/static/ e ver essas alterações refletidas no seu navegador apenas recarregando.
... Mas, como o UWSGI carrega todo o seu aplicativo Web Python Flask quando ele iniciar, você não poderá editar o código do Flask Python e ver as alterações refletidas.
Para poder (temporariamente) depurar o seu código de frasco Python ao vivo, você pode executar seu contêiner substituindo o comando padrão (que inicia o supervisor que, por sua vez, inicia UWSGI e NGINX) e executar seu aplicativo diretamente com python , no modo de depuração, usando o comando flask com suas variáveis de ambiente.
Portanto, com todas as modificações acima e fazendo seu aplicativo funcionar diretamente com flask , o comando final do Docker seria:
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 no caso de um projeto de pacote, você definiria 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=80Agora você pode editar seu código de frasco em sua máquina local e, depois de atualizar o navegador, verá as alterações ao vivo.
Lembre -se de que você deve usar isso apenas para depuração e desenvolvimento, para implantação na produção, você não deve montar volumes e deixar o Supervisord iniciar e deixá -lo iniciar UWSGI e NGINX (que é o que acontece por padrão).
Uma alternativa para essas últimas etapas para funcionar quando você não tem um pacote, mas apenas uma estrutura plana com arquivos únicos (módulos), seu código de frasco Python pode ter essa seção com:
if __name__ == "__main__" :
# Only for debugging while developing
app . run ( host = '0.0.0.0' , debug = True , port = 80 ) ... e você pode executá -lo com python main.py Mas isso só funcionará quando você não estiver usando uma estrutura de pacotes e não planeja fazê -lo mais tarde. Nesse caso específico, se você não adicionasse o bloco de código acima, seu aplicativo apenas ouviria localhost (dentro do contêiner), em outra porta (5000) e não no modo de depuração.
Além disso, se você deseja fazer a mesma depuração ao vivo usando a variável de ambiente STATIC_INDEX=1 (para servir /app/static/index.html diretamente quando solicitado para / ) seu nginx não o servirá diretamente, pois não estará sendo executado (apenas o seu aplicativo Python Flask no modo de depuração estará em execução).
from flask import Flask , send_filee
@ app . route ( '/' )
def route_root ():
index_path = os . path . join ( app . static_folder , 'index.html' )
return send_file ( index_path ) ... Isso garante que seu aplicativo também sirva o arquivo /app/static/index.html quando solicitado para / . Ou se você estiver usando uma estrutura de pacote, o arquivo /app/main/static/index.html .
E se você estiver usando uma estrutura de spa, para permitir que ele manipule os URLs no navegador, o código do frasco do python deve ter a seção com:
# 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 ) ... Isso faz com que o Flask envie todos os arquivos CSS, JavaScript e Image quando solicitado no URL root ( / ), mas também garante que o seu spa de front -end lida com todos os outros URLs que não estão definidos no seu aplicativo Flask.
É assim que está escrito no tutorial acima e está incluído nos exemplos para download.
Se você seguir as instruções acima, é provável que, em algum momento, você escreva código que quebrará seu servidor de depuração de frascos e ele travará.
E como o único processo em execução foi o seu servidor de depuração, que agora está parado, seu contêiner será interrompido.
Em seguida, você terá que iniciar seu contêiner novamente depois de corrigir seu código e não verá com muita facilidade qual é o erro que está travando seu servidor.
Então, enquanto se desenvolve, você pode fazer o seguinte (é isso que normalmente faço, embora eu faça isso com o Docker compor, como nos projetos de exemplo):
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 Agora você estará dentro do seu contêiner no diretório /app .
flask run --host=0.0.0.0 --port=80Você verá o seu servidor de depuração de frascos iniciando, verá como ele envia respostas a todas as solicitações, verá os erros lançados quando quebrar seu código e como eles interromper seu servidor e poderá reiniciá-lo muito rápido, apenas executando o comando acima novamente.
Todas as tags de imagem, configurações, variáveis de ambiente e opções de aplicativos são testadas.
issue-manager.yml . Pr #385 por @tiangolo.latest-changes . Pr #360 por @tiangolo.latest-changes.yml . Pr #348 por @alejsdev.README.md . Pr #346 por @alejsdev. Destaques deste lançamento:
python3.6-2022-11-25 e 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.