***

Author note: You can read this post in English here.

***

Quer aprender a fazer deploy @? Vem que eu te ensino!

O que você vai encontrar nesse tutorial

  • Como criar uma aplica√ß√£o Flask nos moldes do Heroku
  • Como fazer deploy
  • Um pouquinho de Git
  • Um pouquinho de consumo de API

Avisos: Dos dois posts que eu usei de base para escrever esse aqui, um deles era muiiiito antigo e o outro, apesar de recente, n√£o tinha instru√ß√Ķes que correspondem a vers√£o mais atual do Heroku, eles est√£o na sess√£o de links para quem quiser l√™-los.

Heroku quem?

Se voc√™ chegou at√© aqui, √© prov√°vel que voc√™ j√° saiba o que o Heroku √©, mas pra quem ainda n√£o sabe, Heroku √© uma plataforma na nuvem que permite que pessoas ‚Äútransformem suas ideias o mais r√°pido poss√≠vel em uma URL‚ÄĚ e sem ter dores de cabe√ßa com a parte de infraestrutura.

Essa plataforma prov√™ um servi√ßo que, a partir de uma estrutura pr√©-definida de uma aplica√ß√£o, consegue empacotar essa aplica√ß√£o e colocar ela pra rodar num servidor em um dos data centers deles. O Heroku aceita aplica√ß√Ķes escritas em v√°rias linguagens, mas hoje vamos usar Python

Resumo:

tudo computador essa porra

Partiu código!

Pra esse tutorial eu fiz uma API em um microframework Python chamado Flask. N√£o irei explicar em detalhes como o Flask funciona, mas se voc√™ quiser aprender sobre isso, o Bruno Rocha tem um conjunto de posts chamado ‚ÄúWhat the Flask‚ÄĚ que explicam super bem e est√£o todos l√° nos links.

Nossa API

Ela terá apenas um endpoint definido pelo /. Esse endpoint poderá dar duas respostas dependendo da requisição que você faça. São eles:


Requisição Resultado
GET sem cabe√ßalhos (headers) extras N√£o entre em p√Ęnico!
GET com Authorization 42 a resposta para a vida, o universo e tudo mais

O código pra fazer isso fica pequeninho, dá uma olhada:

import os
from flask import Flask, jsonify, request


app = Flask(__name__)

@app.route('/')
def nao_entre_em_panico():
    if request.headers.get('Authorization') == '42':
        return jsonify({"42": "a resposta para a vida, o universo e tudo mais"})
    return jsonify({"message": "N√£o entre em p√Ęnico!"})

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5000))
    app.run(host='0.0.0.0', port=port)

Esse código fica dentro de um arquivo chamado aqui de nao_entre_em_panico.py mas você pode nomear da forma que você achar melhor. Além disso, esse código tem uma peculiaride: as três linhas finais, elas servem para configurar o servidor Flask quando ele estiver rodando no Heroku.

Pipfile

Lembra que eu falei lá no começo que os posts base eram antigos? Pois bem, hoje o Heroku exige um Pipfile para preparar o ambiente em que a nossa aplicação vai rodar. O Pipfile vai servir para instalar as bibliotecas Python necessárias para rodar a nossa aplicação. Se você, assim como eu, não gosta de usar o Pipenv - desculpa Cássio - dá pra criar o arquivo na mão, como criei o meu abaixo:

[[source]]

url = "https://pypi.python.org/simple"
verify_ssl = true


[packages]

Flask = "*"

[requires]

python_version = "3.6"

Para desenvolver (preparar o ambiente local) eu gosto do bom e velho requirements.txt que fica assim:

click==6.7
Flask==0.12.2
itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
Werkzeug==0.14.1

Procfile

No nosso computador, para rodar (colocar de pé) a nossa API o comando é o seguinte:

FLASK_APP=nao_entre_em_panico.py flask run

Como n√£o ser√° voc√™ quem ir√° executar um comando pra colocar a API de p√©, voc√™ vai precisar de um arquivo que vai dizer ‚ÄúColoca a API de p√© a√≠‚ÄĚ para o Heroku, esse arquivo √© o Procfile.

Uma atençãozinha especial para um detalhe: esse arquivo não possui extensão, dependendo do seu sistema operacional e seu editor de texto, na hora de salvaer esse arquivo pode aparecer uma extensão .txt nesse arquivo e isso vai causar uma falha no nosso deploy então, lembre-se de remover a extensão do arquivo caso ela apareça ;)

Para esta aplicação, o Procfile vai ter uma linha só que é a seguinte:

web: python nao_entre_em_panico.py

T√° beleza, e o que mais?

Versionamento

Como o Heroku funciona com o sistema de versionamento Git, independentemente de você hospedar ou não o código no GitHub, nós precisamos criar nosso histórico de versão para a aplicação.

Então, depois de criar todos esses arquivos aqui de cima, você precisa adicionar tudo isso na sua árvore Git. Se você não é lá muito fã de Git pode fazer o seguinte:

$ git init
$ git add .
$ git commit -m "criando a aplicação"

Essa sequência de comandos acima vai colocar todos os arquivos num mesmo commit, isso não é uma boa prática e caso esteja interessada(o) em boas práticas lá no fim do desse tutorial vai ter links sobre isso.

3, 2, 1… Deploy \o/

Agora voc√™ tem uma escolha: existem algumas formas de enviar o seu c√≥digo para o Heroku. Voc√™ pode connectar com o GitHub ou com Dropbox ou ainda usar o Heroku CLI. Nesse post n√≥s vamos fazer da √ļltima forma.

Então, pra começar você precisa instalar o Heroku CLI.

Fazendo login

Começando pelo login:

$ heroku login

Esse comando vai te pedir para digitar e-mail e senha de acesso da sua conta no Heroku:

login heroku

Tela de login da CLI do Heroku

Criando uma aplicação

Usando a interface

√Č poss√≠vel criar uma aplica√ß√£o pela interface do site, onde voc√™ vai ver a seguinte tela:

tela de criação de app no site da heroku

Depois disso você ainda precisa adicionar o remote do Heroku no nosso repositório:

heroku git:remote -a guiaapi

E olha como é a resposta desse comando:

adicionando o remote do Heroku

Usando o terminal

Mas também podemos criar a aplicação usando a CLI do Heroku. O lado bom de usar a CLI é que ao criar a aplicação o remote é criado automaticamente:

heroku apps:create guiaapi

O que deve mostrar algo assim ó:

criação de um app nomeado usando a heroku cli

Pausa para mais um momento de aten√ß√£o: desse jeito que eu mostrei a√≠ em cima, a gente consegue nomear nossa aplica√ß√£o dentro do Heroku, a√≠ que entra uma ‚Äúpegadinha‚ÄĚ, o nome da minha aplica√ß√£o tem que ser √ļnica dentro do Heroku, pois √© o nome da aplica√ß√£o que √© usado para criar a URL dela, se voc√™ por acaso tentar criar uma aplica√ß√£o com um nome j√° utilizado, a resposta para o comando acima vai ser esta:

falha na criação de app usando a heroku cli

Se o nome da sua aplicação não for algo importante, você pode executar o seguinte comando no lugar do comando anterior:

heroku create

Esse comando vai criar uma aplicação com um nome randomizado, por exemplo:

criação de um app usando a heroku cli

Depois de criada a aplica√ß√£o, voc√™ pode dar uma espiada l√° na dashboard do Heroku na √°rea de aplica√ß√Ķes para ver a lista das suas aplica√ß√Ķes:

lista de apps na dashboard da heroku

Finalmente fazendo o bendito deploy

Depois de commitar tudo, fazer login e criar a sua aplicação no Heroku chegou a hora do deploy.

A ação de fazer o deploy, aqui nesse contexto, significa enviar o código da aplicação para o servidor e rodar o processo para colocar nossa API de pé no servidor.

Outros contextos podem trazer varia√ß√Ķes e passos intermedi√°rios desse que estou apresentando, mas aqui como nossa aplica√ß√£o √© simples e o Heroku √© feito para nos ajudar a colocar aplica√ß√Ķes de p√©, o maior trabalho se torna a cria√ß√£o dos arquivos de configura√ß√£o (que j√° criamos) ;)

Então, o comando que vai executar o envio do código para o servidor é:

git push heroku master

Em caso de sucesso você deve ver algo parecido com isso:

Terminal mostrando o deploy

Uma √ļltima configura√ß√£o que pode ser necess√°ria fazer √© garantir que a nossa aplica√ß√£o tem pelo menos um dyno rodando com o seguinte comando:

heroku ps:scale web=1

Dynos

E o que é um dyno? Em resumo um dyno é um Linux Container, o Heroku utiliza um modelo de container que isola a sua aplicação e possibilita a fácil escalabilidade do sistema. Em outras palavras menos técnicas: Pega todos os arquivos de código e configuração que escrevemos até agora e enfia num caixa e bota pra rodar, isso é um dyno.

Agora pra ver o resultado da sua API podemos (nesse caso) abrir um navegador e acessar https://guiaapi.herokuapp.com/ ou usar a linha de comando pra abrir a URL direto:

heroku open

Se deu tudo certo (e você usar o Firefox como navegador) você verá algo assim:

Get sem cabeçalho de autorização no navegador

O que aconteceu foi o seguinte: ao acessar a URL da nossa aplicação no Heroku nós fizemos uma requisição GET pra API com o cabeçalho (header) padrão, ou seja, sem o campo Authorization. Que seria a mesma coisa que rodar no terminal, isso aqui em baixo:

curl -X GET -k -i 'https://guiaapi.herokuapp.com/'

Que me d√° este resultado:

Get sem cabeçalho de autorização no terminal com cURL

Como sabemos, essa nossa API vai ter uma resposta diferente se você passar o cabeçalho Authorization com o valor de 42, veja:

curl -X GET -k -H 'Authorization: 42' \
    -i 'https://guiaapi.herokuapp.com/'

Temos o seguinte resultado:

Get com cabeçalho de autorização no terminal com cURL

Dá pra passar o cabeçalho de autorização no navegador? Dá! mas vou deixar isso pra outro post/tutorial que eu prometo que linko aqui quando escrever.

Overview de um app

Pro tip: Arquivos de log

Pode ser que voc√™ tenha cometido alguma falha no processo de configura√ß√£o da sua aplica√ß√£o e, na hora do deploy, o Heroku avise que ele foi mal-sucedido. Nesse caso o primeiro lugar para procurar informa√ß√Ķes do que deu errado s√£o os logs.

Um bom sistema faz logs de todas as a√ß√Ķes executadas. Nesse nosso caso, o Heroku se encarrega de logar todos os detalhes pra gente, ent√£o basta pedir esse log usando a CLI. Aqui eu ainda escrevo os logs num arquivo para facilitar a inspe√ß√£o, veja:

heroku logs > out.log

Exemplos de linhas que você irá encontrar num desses logs:

...
2018-04-15T02:24:39.000000+00:00 app[api]: Build succeeded
2018-04-15T02:25:11.165813+00:00 heroku[web.1]: Starting process with command `python nao_entre_em_panico.py`
...
2018-04-15T02:52:20.075995+00:00 app[web.1]: 10.5.207.142 - - [15/Apr/2018 02:52:20] "GET / HTTP/1.1" 200 -

Agora se algu√©m falar ‚ÄúFaz um deploy ae!‚ÄĚ voc√™ j√° sabe como ;)

Ps.: Se tiver d√ļvidas ou comenta ali em baixo ou me manda mensagem que eu tento responder, sem crise as DMs t√£o sempre abertas ;)