A previous version of this tutorial was written by Kathleen Juell.
Introdução
Neste guia, você irá construir uma aplicação Python utilizando o microframework Flask no Ubuntu 22.04. A maior parte deste tutorial será sobre como configurar o servidor de aplicação Gunicorn e como lançar a aplicação e configurar o Nginx para atuar como um proxy reverso de front-end.
Pré-requisitos
Antes de iniciar este guia, você deve ter:
-
Um servidor com Ubuntu 22.04 instalado e um usuário não-root com privilégios de 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 22.04.
- Um nome de domínio configurado para apontar para o seu servidor. Você pode comprar um em Namecheap ou obter um gratuitamente em Freenom. Você pode aprender como apontar domínios para o DigitalOcean seguindo a documentação relevante sobre domínios e DNS. Certifique-se de criar os seguintes registros DNS:
- Um registro A com
seu_domínio
apontando para o endereço IP público do seu servidor. - Um registro A com
www.seu_domínio
apontando para o endereço IP público do seu servidor.
- Um registro A com
-
Familiaridade com a especificação WSGI, que o servidor Gunicorn usará para se comunicar com a sua aplicação Flask. Esta discussão aborda o WSGI com mais detalhes.
Passo 1 — Instalando os Componentes dos Repositórios do Ubuntu
O primeiro passo será instalar todas as peças necessárias dos repositórios do Ubuntu. Isso inclui o pip
, o gerenciador de pacotes do Python, que irá gerenciar os componentes Python. Você também obterá os arquivos de desenvolvimento do Python necessários para construir alguns dos componentes do Gunicorn.
Primeiro, atualize o índice de pacotes local e instale os pacotes que permitirão que você construa seu ambiente Python. Estes incluirão o python3-pip
, juntamente com alguns pacotes e ferramentas de desenvolvimento necessários para um ambiente de programação robusto:
Com esses pacotes em vigor, o próximo passo é criar um ambiente virtual para o seu projeto.
Passo 2 — Criando um Ambiente Virtual Python
Em seguida, você configurará um ambiente virtual para isolar a aplicação Flask dos outros arquivos Python em seu sistema.
Comece instalando o pacote python3-venv
, que instalará o módulo venv
:
Em seguida, crie um diretório pai para o seu projeto Flask. Mova-se para o diretório com o comando cd
depois de criá-lo:
Crie um ambiente virtual para armazenar os requisitos do seu projeto Python do Flask digitando:
Isto irá instalar uma cópia local do Python e do pip
em um diretório chamado myprojectenv
dentro do seu diretório de projeto.
Antes de instalar aplicativos dentro do ambiente virtual, você precisa ativá-lo. Faça isso digitando:
Seu prompt mudará para indicar que você está agora operando dentro do ambiente virtual. Parecerá algo assim: (myprojectenv)user@host:~/myproject$
.
Passo 3 — Configurando uma Aplicação Flask
Agora que você está em seu ambiente virtual, você pode instalar Flask e Gunicorn e começar a projetar sua aplicação.
Primeiro, instale o wheel
com a instância local do pip
para garantir que seus pacotes sejam instalados mesmo se estiverem faltando arquivos de roda:
Observação
Independentemente da versão do Python que você estiver usando, quando o ambiente virtual estiver ativado, você deve usar o comando pip
(não pip3
).
Em seguida, instale o Flask e o Gunicorn:
Criando um Aplicativo de Exemplo
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 frameworks mais completos podem ter, e existe principalmente como um módulo que você pode importar em seus projetos para ajudá-lo a inicializar um aplicativo da web.
Embora seu aplicativo possa ser mais complexo, vamos criar nosso aplicativo Flask em um único arquivo, chamado myproject.py
:
O código do aplicativo ficará neste arquivo. Ele importará o Flask e instanciará um objeto Flask. Você pode usar isso para definir as funções que devem ser executadas quando uma rota específica é solicitada:
Isso basicamente define qual conteúdo apresentar quando o domínio raiz é acessado. Salve e feche o arquivo quando terminar.
Se você seguiu o guia de configuração inicial do servidor, você deve ter um firewall UFW ativado. Para testar o aplicativo, você precisa permitir o acesso à porta 5000
:
Agora você pode testar seu aplicativo Flask digitando:
Você verá uma saída como a seguinte, incluindo um aviso útil lembrando você de não usar esta configuração de servidor em 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 por :5000
em seu navegador da web:
http://your_server_ip:5000
Você deverá ver algo como isto:
Quando terminar, pressione CTRL-C
na janela do terminal para parar o servidor de desenvolvimento do Flask.
Criando o Ponto de Entrada WSGI
Em seguida, crie um arquivo que servirá como ponto de entrada para sua aplicação. Isso informará ao servidor Gunicorn como interagir com a aplicação.
Chame o arquivo de wsgi.py
:
Neste arquivo, importe a instância do Flask de nossa aplicação e então execute-a:
Salve e feche o arquivo quando terminar.
Passo 4 — Configurando o Gunicorn
Sua aplicação agora está escrita com um ponto de entrada estabelecido. Agora você pode prosseguir para configurar o Gunicorn.
Antes de prosseguir, verifique se o Gunicorn pode servir a aplicação corretamente.
Você pode fazer isso passando o nome do ponto de entrada da aplicação. Isso é construído como o nome do módulo (sem a extensão .py
), mais o nome do chamável dentro da aplicação. Neste caso, é wsgi:app
.
Também especifique a interface e a porta para se ligar usando o argumento 0.0.0.0:5000
para que a aplicação seja iniciada em uma interface disponível publicamente:
Você deverá ver uma saída como a 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 novamente o endereço IP do seu servidor com :5000
adicionado ao final no seu navegador da web:
http://your_server_ip:5000
Você deve ver a saída do seu aplicativo:
Quando você confirmar que está funcionando corretamente, pressione CTRL-C
na janela do seu terminal.
Quando terminar de usar o ambiente virtual, você pode desativá-lo:
Quaisquer comandos Python agora usarão novamente o ambiente Python do sistema.
Em seguida, crie o arquivo de unidade de serviço systemd. Criar um arquivo de unidade systemd permitirá que o sistema de inicialização do Ubuntu inicie automaticamente o Gunicorn e sirva a aplicação Flask sempre que o servidor for iniciado.
Crie um arquivo de unidade terminando em .service
dentro do diretório /etc/systemd/system
para começar:
Dentro dele, você começará com a seção [Unit]
, que é usada para especificar metadados e dependências. Adicione uma descrição do seu serviço aqui e diga ao sistema de inicialização para iniciar isso apenas depois que o alvo de rede for alcançado:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
Em seguida, adicione uma seção [Service]
. Isso especificará o usuário e o grupo nos quais você deseja que o processo seja executado. Dê à sua conta de usuário regular a propriedade do processo, pois ela possui todos os arquivos relevantes. Dê também a propriedade do grupo ao grupo www-data
para que o Nginx possa se comunicar facilmente com os processos Gunicorn. Lembre-se de substituir o nome de usuário aqui pelo seu nome de usuário:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
Em seguida, mapeie o diretório de trabalho e defina a variável de ambiente PATH
para que o sistema de inicialização saiba que os executáveis do processo estão localizados dentro do nosso ambiente virtual. Especifique também o comando para iniciar o serviço. Este comando fará o seguinte:
- Iniciar 3 processos de trabalho (embora você deva ajustar isso conforme necessário)
- Criar e vincular a um arquivo de soquete Unix,
myproject.sock
, dentro do diretório do nosso projeto. Vamos definir um valor de máscara de permissão de007
para que o arquivo de soquete seja criado dando acesso ao proprietário e ao grupo, enquanto restringe o acesso de outros - Especificar o nome do arquivo de entrada WSGI, juntamente com a função Python dentro desse arquivo (
wsgi:app
)
O Systemd requer que você forneça o caminho completo para o executável do Gunicorn, que está instalado dentro do seu ambiente virtual.
Lembre-se de substituir o nome de usuário e os caminhos do projeto pelas suas próprias informações:
[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
Por fim, adicione uma seção [Install]
. Isso informará ao systemd a que serviço vincular se você habilitá-lo para iniciar durante a inicialização. Você vai querer que este serviço comece quando o sistema de vários usuários regular estiver pronto e em execução:
[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, seu arquivo de serviço do systemd está completo. Salve e feche-o agora.
Agora você pode iniciar o serviço do Gunicorn que você criou e habilitá-lo para que ele inicie durante a inicialização:
Vamos verificar o status:
Você deve ver uma saída como esta:
Output● myproject.service - Gunicorn instance to serve myproject
Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2022-05-10 19:40:41 UTC; 9s ago
Main PID: 17300 (gunicorn)
Tasks: 4 (limit: 2327)
Memory: 56.0M
CPU: 514ms
CGroup: /system.slice/myproject.service
├─17300 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17301 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17302 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
└─17303 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
May 10 19:40:41 r systemd[1]: Started Gunicorn instance to serve myproject.
. . .
Se você ver quaisquer erros, certifique-se de resolvê-los antes de continuar com o tutorial.
Passo 5 — Configurando o Nginx para Encaminhar Solicitações
Seu servidor de aplicativos Gunicorn deve estar agora em funcionamento, aguardando solicitações no arquivo de soquete no diretório do projeto. Agora você pode configurar o Nginx para encaminhar solicitações da web para esse soquete fazendo algumas pequenas adições ao arquivo de configuração dele.
Comece criando um novo arquivo de configuração de bloco de servidor no diretório sites-available
do Nginx. Chame isso de meuprojeto
para manter a consistência com o resto do guia:
Abra um bloco de servidor e diga ao Nginx para ouvir na porta padrão 80
. Também informe que ele deve usar esse bloco para solicitações do nome de domínio do nosso servidor:
server {
listen 80;
server_name your_domain www.your_domain;
}
Em seguida, adicione um bloco de localização que corresponda a todas as solicitações. Dentro deste bloco, você incluirá o arquivo proxy_params
que especifica alguns parâmetros gerais de proxy que precisam ser definidos. Em seguida, passe as solicitações para o soquete que você definiu usando a diretiva 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 de bloco de servidor do Nginx que você acabou de criar, vincule o arquivo ao diretório sites-enabled
:
Com o arquivo nesse diretório, você pode testar erros de sintaxe:
Se isso retornar sem indicar problemas, reinicie o processo do Nginx para ler a nova configuração:
Finalmente, ajuste o firewall novamente. Você não precisa mais de acesso pela porta 5000
, então pode remover essa regra. Você pode então permitir acesso total ao servidor Nginx:
Agora você deve conseguir navegar para o nome de domínio do seu servidor no seu navegador da web:
http://your_domain
Você deverá ver a saída do seu aplicativo:
Nota: Você receberá um erro de gateway HTTP 502 se o Nginx não puder acessar o arquivo de soquete do Gunicorn. Geralmente, isso ocorre porque o diretório pessoal do usuário não permite que outros usuários acessem arquivos dentro dele.
Se o seu arquivo de soquete for chamado /home/sammy/myproject/myproject.sock
, verifique se /home/sammy
tem no mínimo permissões 0755
. Você pode usar uma ferramenta como chmod
para alterar as permissões assim:
Depois recarregue a página para ver se o erro HTTP 502 desaparece.
Se encontrar algum erro, tente verificar o seguinte:
sudo less /var/log/nginx/error.log
: verifica os logs de erro do Nginx.sudo less /var/log/nginx/access.log
: verifica os logs de acesso do Nginx.sudo journalctl -u nginx
: verifica os logs de processo do Nginx.sudo journalctl -u myproject
: verifica os logs do Gunicorn do seu aplicativo Flask.
Passo 6 — Protegendo o Aplicativo
Para garantir que o tráfego para o seu servidor permaneça seguro, vamos obter um certificado SSL para o seu domínio. Existem várias maneiras de fazer isso, incluindo obter um certificado gratuito do Let’s Encrypt, gerar um certificado autoassinado, ou comprar um de outro provedor e configurar o Nginx para usá-lo seguindo as Etapas de 2 a 6 de Como Criar um Certificado SSL Autoassinado para o Nginx no Ubuntu 22.04. Vamos usar a opção um (Let’s Encrypt) por uma questão de rapidez.
Instale o pacote Nginx do Certbot com apt
:
O Certbot fornece uma variedade de maneiras de obter certificados SSL por meio de plugins. O plugin Nginx cuidará de reconfigurar o Nginx e recarregar a configuração sempre que necessário. Para usar este plugin, digite o seguinte:
Isso executa o certbot
com o plugin --nginx
, usando -d
para especificar os nomes que gostaríamos que o certificado fosse válido.
Se esta é a primeira vez que você está executando o certbot
, será solicitado a inserir um endereço de e-mail e concordar com os termos de serviço. Depois de fazer isso, o certbot
irá se comunicar com o servidor Let’s Encrypt e, em seguida, executar um desafio para verificar que você controla o domínio para o qual está solicitando um certificado.
Se isso for bem-sucedido, o certbot
perguntará como você gostaria de configurar 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):
Selecione sua escolha e pressione ENTER
. A configuração será atualizada e o Nginx será recarregado para aplicar as novas configurações. O certbot
concluirá com uma mensagem informando que o processo foi bem-sucedido e onde seus 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 você seguiu as instruções de instalação do Nginx nos pré-requisitos, não precisará mais da permissão redundante do perfil HTTP:
Para verificar a configuração, navegue novamente até o seu domínio, usando https://
:
https://your_domain
Você deverá ver a saída do seu aplicativo novamente, juntamente com o indicador de segurança do seu navegador, que deve indicar que o site está protegido.
Conclusão
Neste guia, você criou e protegeu uma aplicação Flask simples dentro de um ambiente virtual Python. Você criou um ponto de entrada WSGI para que qualquer servidor de aplicação compatível com WSGI possa interagir com ela, e então configurou o servidor de aplicação Gunicorn para fornecer essa função. Em seguida, você criou um arquivo de serviço systemd para iniciar automaticamente o servidor de aplicação na inicialização. Você também criou um bloco de servidor Nginx que encaminha o tráfego do cliente da web para o servidor de aplicação, transmitindo solicitações externas, e protegeu o tráfego para o seu servidor com Let’s Encrypt.
O Flask é um framework muito simples, mas extremamente flexível, destinado a fornecer funcionalidades às suas aplicações sem ser muito restritivo em relação à estrutura e ao design. Você pode usar a pilha geral descrita neste guia para servir as aplicações Flask que você projetar.