Deploy de Flask na Amazon EC2 com Apache

Há umas 4 semanas eu estava na Campus Party e, como eu já tinha feito tudo que eu podia imaginar naquela linda internet de 50GB, fui tentar fazer o deploy da nova versão da Cacho.la na Amazon, utilizando Flask e Apache. Porém, eis que minha aplicação tem uma estrutura em MVC e, às vezes, pode ser meio chato entender as coisas quando todos os exemplos de deploy são para aplicações de um arquivo apenas e a Amazon tem algumas frescuras com permissões que as pessoas esquecem de te avisar. Por esses, entre outros motivos, só consegui fazer o deploy depois de 4 semanas tentando.

Agora, para ajudar aquelas pessoas que, assim como eu, não tem muita experiência nem com Flask nem com Amazon, vamos seguir esse guia para aplicações tanto de grande quanto de pequeno porte.

Primeiro, para vocês terem uma ideia, a estrutura da aplicação é mais ou menos essa:
meuapp/
├── app
│   ├── __init__.py
│   ├── models
│   ├── routes
│   ├── static
│   └── uploads
├── config.py
├── flask #meu virtual enviroment
├── migrations
├── requirements.txt
└── run.py

Essa é a estrutura de uma aplicação MVC de “grande porte”. Agora, se sua aplicação é alguma coisa pequena, você deve ter algo como:

meuapp/
├── app.py
└── flask #meu virtual enviroment

Para fins de entendimento futuro, tanto no meu app/__init__.py do modelo MVC e no meu app.py, tenho:


from flask import Flask
app = Flask(__name__)

Irei exemplificar o modelo de deploy para ambos os tipos de aplicação, então atente-se quando eu estiver demonstrando para uma pequena aplicação ou uma “maiorzinha” e veja qual das duas se encaixa no seu deploy.

Instalação

Antes de tudo, crie uma instância no EC2 da Amazon com as configurações que preferir e acesse-a via SSH (a Amazon te indica o que fazer quando você clica na instância e vai em Connect).

Feito isto, instale tudo o que é necessário para fazer sua aplicação. Ou seja, o Apache, o mod_wsgi e os módulos da sua aplicação. Instale o pip para fazer a instalação dos módulos da aplicação e o git, caso sua aplicação utilize esse sistema de versionamento.


sudo apt-get install apache2 apache2-base apache2-mpm-prefork apache2-utils libexpat1 ssl-cert
sudo apt-get install libapache2-mod-wsgi python-pip git

Para uma aplicação pequena, além dos demais módulos:

pip install flask

Para uma aplicação maiorzinha, por exemplo, a minha:

pip install -r requirements.txt

Caso você não saiba o que é o requirements.txt, ele é um arquivo para indicar todos os módulos que você utiliza no seu ambiente e na aplicação. Por isso, é útil reuni-los nesse arquivo para facilitar o deploy, sempre. Para fazer isso, ative seu venv e faça:

pip freeze > requirements.txt

Agora, para completar a instalação do mod_wsgi, reinicie o Apache:

sudo service apache2 restart

Configuração

Antes de tudo, faça o clone do seu repositório em /var/www/ ou, caso não utilize git, coloque a sua aplicação nesse diretório à sua maneira.


cd /var/www
git clone [seu_repositório]

Agora, para começar a configurar nosso deploy, precisamos criar um arquivo WSGI para indicar ao Python como ele deve se comunicar com o servidor.

import sys
sys.path.insert(0, '/var/www/[meuapp]')

from app import app as application

Modifique [meuapp] pelo nome do diretório que contém sua aplicação.

No caso da aplicação pequena, o primeiro app se refere ao arquivo app.py e o segundo à variável app que associamos ao Flask(__name__).

Já na aplicação “maiorzinha”, o primeiro app se refere ao módulo app, ou seja, a nossa pasta app que contém o __init__.py onde definimos o segundo app igual ao Flask(__name__). Confuso? É só isso que essa linha diz: do módulo (pasta) app importe a variável app.

Note que o application, no final, não pode ser modificado, pois é a forma de o servidor identificar nossa aplicação.

Chame esse arquivo como quiser, eu recomendo [meuapp].wsgi, e salve-o em /var/www/ (ou dentro do repositório da sua aplicação, caso prefira).

Com esse arquivo criado, precisamos configurar o Apache para utilizar o mod_wsgi. Para isso, acesse /etc/apache2/sites-available/ e crie um novo arquivo. Iremos chamá-lo de amazonaws.com.conf. Esse arquivo é o que irá indicar ao Apache o que fazer para deixar nosso site acessível. Preencha da seguinte maneira:

NameVirtualHost *:80

<VirtualHost *:80>
ServerName [o DNS público da sua instância no EC2 aqui]
WSGIScriptAlias / /var/www/[meuapp].wsgi
<Directory /var/www/[meuapp]/>
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel info
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

O DNS público da sua instância pode ser obtido nas informações dela, ao clicar em cima da instância no menu do EC2. Se, por algum acaso, sua instância não tiver um DNS público sendo exibido, pode ser que seu VPC esteja mal configurado (como foi o meu caso, não faço ideia do motivo). Para resolver isso acesse http://console.aws.amazon.com, vá no menu Services -> VPC, abra Your VPCs e selecione seu VPC que está conectado ao EC2. Depois, vá em Summary e modifique o DNS hostnames para YES. Isso deve resolver.

Ainda sobre o arquivo acima, note que o primeiro [meuapp].wsgi é o arquivo que acabamos de criar, então aponte o caminho certo para ele, onde quer que tenha decidido colocar, e o nome que deu para ele. Já o segundo [meuapp] é o nome do diretório onde está a sua aplicação. Independente da aplicação ser de grande ou pequeno porte, você deve indicar o caminho do diretório raíz.

Agora, devemos desativar o site padrão do Apache e ativar o nosso.

sudo a2dissite 000-default
sudo a2ensite amazonaws.com

Por fim, vamos reiniciar o Apache!

sudo service apache2 reload

Pronto! Seu app Flask já deve estar rodando, basta acessar o DNS público que a Amazon fornece e verá ele sendo exibido lindamente.

Caso seu app não esteja funcionando, atente-se a alguns detalhes.

1. Verifique bem a estrutura de aplicação exibida aqui. Pode ser que você tenha uma pasta com o __init__.py definindo o Flask(), mas ela não se chame app como aqui no post ou seu arquivo app.py não tenha esse nome, então o import de application não daria certo;

2. Verifique se todos os caminhos que você definiu estão corretos;

3. Confira o log de erros do Apache, geralmente em /var/logs/apache2/error.log, e verifique o problema que aparece;

4. Se o problema é o carregamento do seu app, isto é, quando você acessa o DNS público ele não carrega nada, nem uma página de erro, simplesmente não entra em lugar nenhum, o problema real é o grupo de segurança (Security Group) da sua instância. Isso pode ser solucionado da seguinte maneira: selecione sua instância e vá em Actions -> Networking -> Change Security Groups. Modifique para um grupo que tenha acesso aberto (IP 0.0.0.0). Caso esse grupo não exista, pode ser criado pelo menu lateral em Security Groups com o IP indicado acima, isto é, uma configuração de All trafic.

Espero ter salvado vidas! 😀

Referência: http://alex.nisnevich.com/blog/2014/10/01/setting_up_flask_on_ec2.html

3 comentários sobre “Deploy de Flask na Amazon EC2 com Apache

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.