Neste guia, você construirá um aplicativo Python usando o microframework Flask no Ubuntu 20.04. A maior parte deste artigo será sobre como configurar o servidor do aplicativo Gunicorn, como iniciar o aplicativo e configurar o Nginx para atuar como um proxy reverso no front-end.
Antes de iniciar este guia, você deve ter:
Um servidor com o Ubuntu 20.04 instalado e um usuário não root com privilégios sudo. Siga nosso guia de configuração inicial do servidor para orientação.
O Nginx instalado, seguindo os Passos 1 e 2 de Como instalar o Nginx no Ubuntu 20.04.
Um nome de domínio configurado para apontar para o seu servidor. Você pode comprar um no Namecheap ou obter um de graça no Freenom. Você pode aprender como apontar domínios para o DigitalOcean seguindo a relevante documentação para domínios e DNS. Certifique-se de criar os seguintes registros DNS:
your_domain
apontando para o endereço IP público do seu servidor.www.your_domain
apontando para o endereço de IP público do seu servidor.Familiarize-se com a especificação do WSGI, que o servidor do Gunicorn usará para se comunicar com seu aplicativo Flask. Esta discussão aborda mais detalhadamente o WSGI.
Nosso primeiro passo será instalar todas as partes que precisamos dos repositórios do Ubuntu. Isso inclui o pip
, o gerenciador de pacotes Python que irá gerenciar nossos componentes Python. Também vamos obter os arquivos de desenvolvimento do Python necessários para construir alguns dos componentes do Gunicorn.
Primeiramente, vamos atualizar o índice local de pacotes e instalar os pacotes que irão nos permitir construir nosso ambiente Python. Estes incluem o python3-pip
, junto com alguns outros pacotes e ferramentas de desenvolvimento necessários para um ambiente de programação robusto:
- sudo apt update
- sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools
Com esses pacotes instalados, vamos seguir em frente para criar um ambiente virtual para nosso projeto.
Em seguida, vamos configurar um ambiente virtual para isolar nosso aplicativo Flask dos outros arquivos Python no sistema.
Inicie instalando o pacote python3-venv
, que instalará o módulo venv
:
- sudo apt install python3-venv
Em seguida, vamos fazer um diretório pai para nosso projeto Flask. Acesse o diretório após criá-lo:
- mkdir ~/myproject
- cd ~/myproject
Crie um ambiente virtual para armazenar os requisitos Python do projeto Flask digitando:
- python3 -m venv myprojectenv
Isso instalará uma cópia local do Python e do pip
em um diretório chamado myprojectenv
dentro do diretório do seu projeto.
Antes de instalar aplicativos no ambiente virtual, você precisa ativá-lo. Faça isso digitando:
- source myprojectenv/bin/activate
Seu prompt mudará para indicar que você agora está operando no ambiente virtual. Ele se parecerá com isso: (myprojectenv)user@host:~/myproject$
.
Agora que você está no seu ambiente virtual, instale o Flask e o Gunicorn e comece a projetar seu aplicativo.
Primeiramente, vamos instalar o wheel
com a instância local do pip
para garantir que nossos pacotes sejam instalados mesmo se estiverem faltando arquivos wheel:
- pip install wheel
Nota
Independentemente da versão do Python que você estiver usando, quando o ambiente virtual for ativado, você deve usar o comando pip
(não o pip3
).
Em seguida, vamos instalar o Flask e o Gunicorn:
- pip install gunicorn flask
Agora que você tem o Flask disponível, você pode criar um aplicativo simples. O Flask é um microframework. Ele não inclui muitas das ferramentas que os frameworks mais completos talvez tenham. Ele existe, principalmente, como um módulo que você pode importar para seus projetos para ajudá-lo na inicialização de um aplicativo Web.
Embora o seu aplicativo possa ser mais complexo, vamos criar nosso app Flask em um único arquivo, chamado myproject.py
:
- nano ~/myproject/myproject.py
O código do aplicativo ficará neste arquivo. Ele importará o Flask e instanciará um objeto Flask. Você pode usar isto para definir as funções que devem ser executadas quando uma rota específica for solicitada:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "<h1 style='color:blue'>Hello There!</h1>"
if __name__ == "__main__":
app.run(host='0.0.0.0')
Isso define basicamente qual conteúdo apresentar quando o domínio raiz for acessado. Salve e feche o arquivo quando você terminar.
Se você seguiu o guia de configuração inicial do servidor, você deverá ter um firewall UFW ativado. Para testar o aplicativo, será necessário permitir o acesso à porta 5000:
- sudo ufw allow 5000
Agora é possível testar seu app Flask digitando:
- python myproject.py
Você verá um resultado como o seguinte, incluindo um aviso útil lembrando para não usar essa configuração de servidor na produção:
Output* Serving Flask app "myproject" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Visite o endereço IP do seu servidor seguido de :5000
no seu navegador Web:
http://your_server_ip:5000
Você deve ver algo como isto:
Quando terminar, tecle CTRL-C
na janela do seu terminal para parar o servidor de desenvolvimento Flask.
Em seguida, vamos criar um arquivo que servirá como o ponto de entrada para nosso aplicativo. Isso dirá ao nosso servidor do Gunicorn como interagir com o aplicativo.
Vamos chamar o arquivo de wsgi.py
:
- nano ~/myproject/wsgi.py
Neste arquivo, vamos importar a instância Flask do nosso aplicativo e então executá-lo:
from myproject import app
if __name__ == "__main__":
app.run()
Salve e feche o arquivo quando você terminar.
Seu aplicativo agora está gravado com um ponto de entrada estabelecido. Podemos agora seguir em frente para configurar o Gunicorn.
Antes de continuar, devemos verificar se o Gunicorn pode atender o aplicativo corretamente.
Podemos fazer essa verificação simplesmente passando o nome do nosso ponto de entrada para o Gunicorn. Criamos esse ponto de entrada como o nome do módulo (menos a extensão .py
) mais o nome do objeto callable dentro do aplicativo. No nosso caso, trata-se do wsgi:app
.
Também vamos especificar a interface e a porta a vincular, de modo que o aplicativo seja iniciado em uma interface disponível publicamente:
- cd ~/myproject
- gunicorn --bind 0.0.0.0:5000 wsgi:app
Deverá ver um resultado como o seguinte:
Output[2020-05-20 14:13:00 +0000] [46419] [INFO] Starting gunicorn 20.0.4
[2020-05-20 14:13:00 +0000] [46419] [INFO] Listening at: http://0.0.0.0:5000 (46419)
[2020-05-20 14:13:00 +0000] [46419] [INFO] Using worker: sync
[2020-05-20 14:13:00 +0000] [46421] [INFO] Booting worker with pid: 46421
Visite o endereço IP do seu servidor com :5000
anexado ao final no seu navegador Web novamente:
http://your_server_ip:5000
Você deve ver o resultado do seu aplicativo:
Quando você tiver confirmado que ele está funcionando corretamente, pressione CTRL-C
na janela do seu terminal.
Acabamos agora o nosso ambiente virtual, para que possamos desativá-lo:
- deactivate
Agora, qualquer comando Python voltará a usar o ambiente do sistema Python.
Em seguida, vamos criar o arquivo da unidade de serviço systemd. Criar um arquivo de unidade systemd permitirá que o sistema init do Ubuntu inicie automaticamente o Gunicorn e atenda o aplicativo Flask sempre que o servidor inicializar.
Crie um arquivo de unidade que termine com .service
dentro do diretório /etc/systemd/system
para começar:
- sudo nano /etc/systemd/system/myproject.service
Ali, vamos começar com a seção [Unit]
, que é usada para especificar os metadados e dependências. Vamos colocar uma descrição do nosso serviço aqui e dizer ao sistema init para iniciar isso somente após o objetivo da rede ter sido alcançado:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
Em seguida, vamos abrir a seção [Service]
. Isso especificará o usuário e o grupo sob o qual que queremos que o processo seja executado. Vamos dar à nossa conta de usuário regular a propriedade sobre o processo, uma vez que ela possui todos os arquivos relevantes. Vamos também dar a propriedade sobre o grupo para o grupo www-data
, de modo que o Nginx possa se comunicar facilmente com os processos do Gunicorn. Lembre-se de substituir o nome de usuário abaixo pelo seu nome de usuário:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
Em seguida, vamos mapear o diretório de trabalho e definir a variável de ambiente PATH
para que o sistema init saiba que os executáveis do processo estão localizados dentro do nosso ambiente virtual. Vamos também especificar o comando para iniciar o serviço. Este comando fará o seguinte:
myproject.sock
, dentro de nosso diretório de projeto. Vamos definir um valor de umask de 007
para que o arquivo socket seja criado dando acesso ao proprietário e ao grupo, ao mesmo tempo que restringe outros acessoswsgi:app
)O systemd exige que seja dado o caminho completo para o executável do Gunicorn, que está instalado dentro do nosso ambiente virtual.
Lembre-se de substituir o nome de usuário e os caminhos do projeto por seus próprios dados:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
Finalmente, vamos adicionar uma seção [Install]
. Isso dirá ao systemd ao que vincular este serviço se nós o habilitarmos para iniciar na inicialização. Queremos que este serviço comece quando o sistema regular de vários usuários estiver funcionando:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
[Install]
WantedBy=multi-user.target
Com isso, nosso arquivo de serviço systemd está completo. Salve e feche-o agora.
Podemos agora iniciar o serviço Gunicorn que criamos e habilitá-lo para que ele seja iniciado na inicialização:
- sudo systemctl start myproject
- sudo systemctl enable myproject
Vamos verificar o status:
- sudo systemctl status myproject
Você deve ver um resultado como este:
Output● myproject.service - Gunicorn instance to serve myproject
Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2020-05-20 14:15:18 UTC; 1s ago
Main PID: 46430 (gunicorn)
Tasks: 4 (limit: 2344)
Memory: 51.3M
CGroup: /system.slice/myproject.service
├─46430 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─46449 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─46450 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
└─46451 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
Se encontrar erros, certifique-se de resolvê-los antes de continuar com o tutorial.
Nosso servidor do aplicativo Gunicorn deve estar funcionando agora, esperando pedidos no arquivo de socket no diretório do projeto. Vamos agora configurar o Nginx para passar pedidos Web para aquele socket, fazendo algumas pequenas adições ao seu arquivo de configuração.
Comece criando um novo arquivo de configuração do bloco do servidor no diretório sites-available
do Nginx. Vamos chamá-lo de myproject
para mantê-lo alinhado com o resto do guia:
- sudo nano /etc/nginx/sites-available/myproject
Abra um bloco de servidor e diga ao Nginx para escutar na porta padrão 80
. Vamos também dizer a ele para usar este bloco para pedidos para o nome de domínio do nosso servidor:
server {
listen 80;
server_name your_domain www.your_domain;
}
Em seguida, vamos adicionar um bloco de localização que corresponda a cada pedido. Dentro deste bloco, vamos incluir o arquivo proxy_params
que especifica alguns parâmetros gerais de proxy que precisam ser configurados. Vamos então passar os pedidos para o socket que definimos usando a diretriz proxy_pass
:
server {
listen 80;
server_name your_domain www.your_domain;
location / {
include proxy_params;
proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
}
}
Salve e feche o arquivo quando terminar.
Para habilitar a configuração do bloco do servidor Nginx que acabou de criar, vincule o arquivo ao diretório sites-enabled
:
- sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Com o arquivo naquele diretório, você pode testar quanto a erros de sintaxe:
- sudo nginx -t
Se retornar sem indicar quaisquer problemas, reinicie o processo Nginx para ler a nova configuração:
- sudo systemctl restart nginx
Finalmente, vamos ajustar o firewall novamente. Já não precisamos de acesso através da porta 5000
, então podemos remover essa regra. Podemos então conceder acesso total ao servidor Nginx:
- sudo ufw delete allow 5000
- sudo ufw allow 'Nginx Full'
Agora, você consegue navegar até o nome de domínio do seu servidor no seu navegador Web:
http://your_domain
Você deve ver o resultado do seu aplicativo:
Caso encontre quaisquer erros, tente verificar o seguinte:
sudo less /var/log/nginx/error.log
: verifica os registros de erros do Nginx.sudo less /var/log/nginx/access.log
: verifica os registros de acesso do Nginx.sudo journalctl -u nginx
: verifica os registros de processo do Nginx.sudo journalctl -u myproject
: verifica os registros do Gunicorn do seu app Flask.Para garantir que o tráfego para seu servidor permaneça protegido, vamos obter um certificado SSL para seu domínio. Há várias maneiras de fazer isso, incluindo a obtenção de um certificado gratuito do Let’s Encrypt, gerando um certificado autoassinado ou comprando algum de outro provedor e configurando o Nginx para usá-lo, seguindo os Passos 2 a 6 de Como criar um certificado SSL autoassinado para o Nginx no Ubuntu 20.04. Vamos escolher a opção um por questão de conveniência.
Instale o pacote Nginx do Certbot com o apt
:
- sudo apt install python3-certbot-nginx
O Certbot oferece várias maneiras de obter certificados SSL através de plug-ins. O plug-in Nginx cuidará da reconfiguração do Nginx e recarregará a configuração sempre que necessário. Para usar este plug-in, digite o seguinte:
- sudo certbot --nginx -d your_domain -d www.your_domain
Esse comando executa o certbot
com o plug-in --nginx
, usando -d
para especificar os nomes para os quais desejamos um certificado válido.
Se essa é a primeira vez que você executa o certbot
, você será solicitado a informar um endereço de e-mail e concordar com os termos de serviço. Após fazer isso, o certbot
se comunicará com o servidor da Let’s Encrypt, executando posteriormente um desafio para verificar se você controla o domínio para o qual está solicitando um certificado.
Se tudo correr bem, o certbot
perguntará como você quer definir suas configurações de HTTPS:
OutputPlease choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):
Select your choice then hit ENTER
. A configuração será atualizada e o Nginx recarregará para aplicar as novas configurações. O certbot
será encerrado com uma mensagem informando que o processo foi concluído e onde os certificados estão armazenados:
OutputIMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/your_domain/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/your_domain/privkey.pem
Your cert will expire on 2020-08-18. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
Se seguiu as instruções de instalação do Nginx nos pré-requisitos, a permissão do perfil HTTP redundante não é mais necessária:
- sudo ufw delete allow 'Nginx HTTP'
Para verificar a configuração, navegue novamente para seu domínio, usando https://
:
https://your_domain
Você deve ver novamente o resultado do seu aplicativo, junto com o indicador de segurança do seu navegador, o qual deve indicar que o site está protegido.
Neste guia, você criou e protegeu um aplicativo Flask simples em um ambiente virtual Python. Você criou um ponto de entrada da WSGI para que qualquer servidor de aplicativo compatível com a WSGI possa interagir com ela, e então configurou o servidor de app Gunicorn para fornecer essa função. Depois, criou um arquivo de serviço systemd para iniciar automaticamente o servidor do aplicativo na inicialização. Você também criou um bloco de servidor Nginx que passa o tráfego Web do cliente para o servidor do aplicativo - retransmitindo pedidos externos - e protegeu o tráfego para seu servidor com o Let’s Encrypt.
O Flask é um framework muito simples - mas extremamente flexível, destinado a fornecer funcionalidade a seus aplicativos sem ser restritivo demais em termos de estrutura e design. Você pode usar a pilha geral descrita neste guia para atender os aplicativos flask que projetar.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!