Deploy de aplicações Rails e Django no Heroku
Autor: fabiolnm | Publicado: 2011-11-13T14:19:00-02:00

No post anterior foi mostrada a importância de se colocar o projeto num servidor de controle de versões, mesmo logo após a sua criação. Algumas preocupações puderam ser rapidamente testadas e solucionadas, por exemplo o setup em máquinas de outros desenvolvedores.

Ainda nesta fase tão precoce, podemos ir mais além: testar o deploy da aplicação num ambiente production-like. Desta forma, cria-se uma cultura de, em cada iteração, testar de ponta-a-ponta o processo de desenvolvimento.


Um dos objetivos é antecipar questões e riscos que tradicionalmente só seriam atacados ao final do projeto. Caso surjam problemas de integração, ou dificuldades técnicas que possam colocar em risco a subida do sistema para produção, as causas podem ser prontamente diagnosticadas e tratadas o mais cedo possível antes que possam comprometer o sucesso do projeto.


Setup do Heroku

O Heroku é uma opção muito popular para o deploy de aplicações Rails, que consiste simplesmente em executar:


git push heroku master


ou seja, pushando o projeto para um repositório Git remoto no Heroku.


A preparação é semelhante a da criação de uma conta no Github. É necessário criar uma conta no Heroku, e fazer o upload de uma chave pública para administração da conta via terminal.


Instalação

O primeiro passo é instalar a gem do heroku:


gem install heroku


Chave pública

Em seguida, fazer o upload da chave pública:
 


Caso o heroku não encontre uma chave pública em ~/.ssh/id_rsa.pub, e também não exista a chave privada ~/.ssh/id_rsa correspondente, o próprio heroku é capaz de gerar estas chaves para nós (como mostrado no trecho acima).

Podemos também aproveitar a chave pública do github, bastando que ela esteja presente em ~/.ssh/id_rsa.pub para ser upada para o heroku.

Caso mais de uma chave esteja presente no diretório .ssh, o heroku pergunta qual deve ser usada:
 


Criação da aplicação no Heroku

Resolvida a questão das chaves, podemos criar a aplicação no heroku:

 

Este comando cria um ambiente no Heroku e o adiciona automaticamente como um repositório Git remoto do projeto, o que pode ser confirmado:
 

Note também que, após deployada, a aplicação responderá inicialmente no endereço http://afternoon-robot-3025.heroku.com.


Deploy de uma aplicação Rails no Heroku
Dispensa comentários:
 

Até mesmo para abrir o navegador, o heroku ajuda:


heroku open



Rackfile e Procfile
O Heroku consegue fazer o deploy de aplicações Rails devido à presença do arquivo config.ru na raiz do projeto. Trata-se de um arquivo Rack, que instrui ao Heroku a forma como a aplicação é iniciada:

 


Procfile e Foreman

Uma alternativa ao Rack é criar um arquivo Procfile na raiz do projeto. Trata-se de um mecanismo de declarar quais comandos devem ser executados ao deployar na plataforma Heroku. Ele consiste de um conjunto de pares informando o tipo de processo e o comando para executar um determinado processo: 

 

Apesar de opcional em aplicações Rails, seu uso é recomendado pois proporciona maior controle e flexibilidade para a aplicação. Além disso, o Heroku provê o comando heroku scalepara ajustar como escalar a aplicação, baseados no Procfile.



Para executar localmente aplicações baseadas no Procfile, é necessário instalar o Foreman.



gem install foreman




Ao iniciar a aplicação com o foreman, ele inicia cada um dos processos declarados no Procfile:
 



Django e Heroku
Conforme anunciado neste post,
o Heroku também oferece suporte a Python, no stack* Cedar, baseado no Ubuntu 10.04.
* o Heroku oferece diferentes stacks - ambientes completos de deploy, incluindo o sistema operacional e bibliotecas associadas.



Para criar um ambiente no stack cedar, é necessário executar o comando:


heroku create --stack cedar


e o deploy também é feito via git push:

 



Porém, como se vê acima, o push é rejeitado, informando que o Heroku não consegue detectar nenhuma aplicação Rails/Rack. Alguns ajustes são necessários para conseguir realizar o deploy da aplicação Django no Heroku.

Procfile para rodar aplicações Django no Heroku
Aplicações que NÃO são baseadas no Rack podem ser deployadas no Heroku usando o Procfile. No caso de uma aplicação Django, basta criar um Procfile com o seguinte conteúdo:



web: python manage.py runserver



que a aplicação passa a ser inicializável via foreman:
 



Agora que está tudo rodando localmente, basta apenas fazer o deploy e correr pro abraço, vai dar até pra sair mais cedo e pegar um cineminha:

 

Oooops... Agora, através do Procfile, o Heroku já é capaz de reconhecer que se trata de uma aplicação Python, porém continua rejeitando o deploy, com uma enigmática mensagem "Django app must be in a subdirectory".



Ainda bem que o Google e o Stack Overflow existem, e alguém já havia postado a solução para este problema: http://stackoverflow.com/questions/7974902/deploying-existing-django-app-on-heroku. 



Para deployar a aplicação Django no Heroku, ela precisa estar organizada de tal forma que o Procfile e o requirements.txt fiquem na raiz do repositório, e o projeto Django deve ser um subdiretório a partir da raiz do repositório.





Com esta nova organização, é importante assegurar que o arquivo settings.py esteja com o valor correto para a propriedade ROOT_URLCONF:


ROOT_URLCONF = 'urls'



Ajustada a estrutura do projeto, aí sim, esperamos que o deploy seja bem sucedido.

 



Basta agora um heroku open e ver se o navegador abre a página e... Ooops. Nada acontece:



A essas alturas, cineminha já era... Neste caso, nem com ajuda de Google e Stack Overflow surgiu alguma pista. Recorrendo ao comando


heroku logs


é possível visualizar o log da subida da aplicação no Heroku, tentando procurar alguma pista sobre o que está faltando:

 

Voilá, nos logs surge a pista: a aplicação crasheou durante a subida, devido à ausência do módulo psycopg2. 


Googleando um pouco mais, surge este blog, com instruções simples para instalar localmente este módulo:

Pré-requisito: 
sudo apt-get install libpq-dev python-dev

Instalação: adicionar ao requirements.txt a linha
psycopg2==2.4.2

Executar
pip install -r requirements.txt




Após nova subida, é cruzar os dedos e... nada! Eis o novo log:

 




Ao que o erro indica, o Heroku não faz o binding na porta 8000, e sugere pesquisar a variável de ambiente PORT. Um tanto enigmático. Recorrendo mais uma vez ao Google, eis uma pista melhor, nos comentários deste blog:


"Creating a Procfile and adding: "web: play run --http.port=$PORT $PLAY_OPTS" fixed the problem." (Ivar Abrahamsen)



o que nos conduz a alterar o Procfile para:



web: python manage.py runserver 0.0.0.0:$PORT



E finalmente:


Deploy de aplicação Django no Heroku - Resumo

O projeto Django deve ser um subdiretório a partir da raiz que é comitada no Git
Alterar o settings.py, fazendo

ROOT_URLCONF = 'url'

Adicionar um Procfile na raiz do projeto contendo:

web: python manage.py runserver 0.0.0.0:$PORT


Instalar o psycopg2

Para deployar no Heroku é suficiente adicionar ao requirements.txt: psycopg2==2.4.2
Para instalar localmente, é necessário:

Instalar pré-requisitos sudo apt-get install libpq-dev python-dev
Invocar o PIP pra instalar o pycopg2pip install -r requirements.txt



Deploy: git push heroku master


Considerações Finais

As tentativas que envidamos para conseguir subir a aplicação Django no Heroku reforçam a tese da importância de testar o processo de desenvolvimento de ponta-a-ponta. Em cada iteração, é importante incluir o deploy para um ambiente production-like, para identificar dificuldades e riscos iterativamente, à medida que a aplicação é desenvolvida.