Deploy de uma aplicação Flask na Vercel (serverless)
Introdução
Se você tem uma aplicação Python saiba que a Vercel pode ser uma solução gratuita para você fazer de deploy de suas aplicações como arquitetura serverless.
- Limitação: Se você usa Python e desenvolve para Web, provavelmente usa Django. O Django é muito vínculado ao SQL. Se você precisa migrar dados num banco de dados SQL, a Vercel não é a solução para você. Pense não é um servidor que você levanta, cria arquivo de migração e faz migração.
- Para quem isso serve, então? Qualquer pessoa que tenha uma aplicação Python que só faz aquisições HTML, renderizar HTML, ou que tenha uma API REST, por exemplo. Irei mostrar algumas possibilidades futuramente. Mas caso queira testar algum banco para serverless vejo como facilidade usar um MongoDB e DynamoDB.
Iniciando com Flask Framework
Flask é o principal micro framework do Python para criar aplicativos Web. Apesar de ser minimalista, podemos criar, com flexibilidade, muitas aplicações.
Você pode se aprofundar no Flask olhando sua documentação. Veja também
- https://flask-restx.readthedocs.io/en/latest/ (Documentar sua API REST)
- https://flask-sqlalchemy.palletsprojects.com/en/2.x/ (Camada de abstração de banco de dados SQL)
Na aplicação criada, não serão explicados todos os detalhes, já que essa não é a finalidade. O Flask foi escolhido justamente por minimalista. Por inspeção, já conseguimos entender o básico de seu funcionamento.
Vamos lá.
Primeiros passos da nossa aplicação
O primeiro passo é ter instalado em sua máquina o Python 3 e Node.js. Se você usa Linux com Kernel recente, o Python já deve instalado.
Instalando a CLI da Vercel
Com nodejs
instalado, vamos instalar a CLI da Vercel globalmente com
npm i -g vercel
Criando ambiente de desenvolvimento
Outro passo é criar um ambiente de desenvolvimento virtual para rodar o projeto. Geralmente, recomendam o uso do virtualenv
, mas pode ser usado o modulo venv
também.
Nesse link mostro como instalar o miniconda
e criar um ambiente de desenvolvimento. A vantagem do miniconda
é que podemos instalar o nodejs
também.
Configurando o projeto
Vamos criar uma simples aplicação, com algumas rotas. Nada muito complicado. Teremos a estrutura recomendada pela Vercel
.
├── api
│ └── index.py
├── data
│ └── data.json
├── requirements.txt
└── vercel.json
A pasta api
terá nossa aplicação Flask. A pasta data
podemos colocar aquivos para serem lidos. O arquivo requirements.txt
terá as dependências do nosso projeto. Por último, o arquivo vercel.json
será responsável por configurar nosso projeto para subir na Vercel.
Primeiro, criaremos uma pasta para o projeto para adicionarmos esses arquivos
mkdir vercel-flask-app
cd vercel-flask-app
Na minha máquina, usei o modulo venv
para criar o ambiente virtual
python3 -m venv venv
. venv/bin/activate
Se preferir o virtualenv
virtualenv venv
. venv/bin/activate
Agora com ambiente ativado podemos instalar as dependências
pip install Flask
Seguinda a estrutua proposta, abra arquivo index.py
com seu editor favorito. Recomendo o VSCode, Sublime Text 3 etc.
from flask import Flask, jsonify, json
from os.path import join
# Criando um dado de teste
livros = [
{
"id": 0,
"titulo": "1984",
"autor": "George Orwell",
"ano_publicao": "1949"
},
{
"id": 1,
"titulo": "Laranja Mecânica",
"autor": "Anthony Burgess",
"ano_publicao": "1962"
},
{
"id": 2,
"titulo": "Admirável Mundo Novo",
"autor": "Aldous Huxley",
"ano_publicao": "1932"
}
]
app = Flask(__name__)
@app.route('/', methods=['GET'])
def home():
return '<h1>Página da rota Home</h1>'
@app.route('/sobre', methods=['GET'])
def about():
return '<h1>Pagina da rota Sobre</h1>'
@app.route('/portfolio', methods=['GET'])
def portfolio():
return '<h1>Página da rota Portfolio</h1>'
@app.route('/contato', methods=['GET'])
def contact():
return '<h1>Página da rota Contato</h1>'
# Puxando dados de data.json e serializando
@app.route("/api/cervejas", methods=['GET'])
def api():
with open('data/data.json', 'r') as file:
data = json.load(file)
return jsonify(data)
# Serializando nosso dado de teste
@app.route('/api/livros', methods=['GET'])
def api_all():
return jsonify(livros)
if __name__ == '__main__':
app.run()
Criamos algumas rotas. Note que a rota /api/cervejas
precisa do arquivo data.json
. Vamos preencher esse arquivo
[
{
"address_2": null,
"address_3": null,
"brewery_type": "planning",
"city": "Austin",
"country": "United States",
"county_province": null,
"created_at": "2018-07-24T00:00:00.000Z",
"id": 9094,
"latitude": null,
"longitude": null,
"name": "Bnaf, LLC",
"obdb_id": "bnaf-llc-austin",
"phone": null,
"postal_code": "78727-7602",
"state": "Texas",
"street": null,
"updated_at": "2018-07-24T00:00:00.000Z",
"website_url": null
},
{
"address_2": null,
"address_3": null,
"brewery_type": "regional",
"city": "Boulder",
"country": "United States",
"county_province": null,
"created_at": "2018-07-24T00:00:00.000Z",
"id": 9180,
"latitude": "40.026439",
"longitude": "-105.2480158",
"name": "Boulder Beer Co",
"obdb_id": "boulder-beer-co-boulder",
"phone": null,
"postal_code": "80301-5401",
"state": "Colorado",
"street": "2880 Wilderness Pl",
"updated_at": "2018-08-24T00:00:00.000Z",
"website_url": null
},
{
"address_2": null,
"address_3": null,
"brewery_type": "planning",
"city": "Clermont",
"country": "United States",
"county_province": null,
"created_at": "2018-07-24T00:00:00.000Z",
"id": 9754,
"latitude": null,
"longitude": null,
"name": "Clermont Brewing Company",
"obdb_id": "clermont-brewing-company-clermont",
"phone": null,
"postal_code": "34711-2108",
"state": "Florida",
"street": null,
"updated_at": "2018-08-11T00:00:00.000Z",
"website_url": null
}
]
Esses dados foram retirados de um banco de dados chamado open brewery db.
Agora no terminal
python index.py
Por padrão, o Flask utiliza a porta 5000. Então, em seguida abra o link http://127.0.0.1:5000/ no seu navegador.
Você pode verificar se todas as rotas estão funcionando
- http://127.0.0.1:5000/
- http://127.0.0.1:5000/about
- http://127.0.0.1:5000/portfolio
- http://127.0.0.1:5000/contact
- http://127.0.0.1:5000/api/cervejas
- http://127.0.0.1:5000/api/livros
Deploy na Vercel e Serverless Functions
Vercel é uma plataforma em nuvem para sites estáticos (Jamstack) e Serverless Functions que se adapta perfeitamente ao seu fluxo de trabalho. Ele permite que os desenvolvedores hospedem sites e serviços da web com deploys instantâneos, escalados automaticamente e não requer supervisão, tudo sem configuração.
A Vercel também é o responsável pelo incrível Next.js.
Há duas formas para o deploy. Aqui mostrarei como fazer localmente. A outra forma seria usar um repositório Git (Gitlab, GitHub, BitBucket).
Lembra da estrutura de pastas?
.
├── api
│ └── index.py
├── data
│ └── data.json
├── requirements.txt
└── vercel.json
Não importando a forma de deploy, precisaremos criar um arquivo com as dependências do projeto. Para isso
pip freeze > requirements.txt
que passará todos os pacotes instalados no nosso ambiente para o arquivo requirements.txt
Agora precisaremos editar o arquivo vercel.json
na raiz do projeto com as algumas informações. Esse arquivo é o responsável de explicar que temos uma aplicação Python e, se houverem, quais são suas rotas (para mais informações)
{
"version": 2,
"builds": [
{
"src": "api/index.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "/",
"dest": "/api/index.py"
},
{
"src": "/contato",
"dest": "/api/index.py"
},
{
"src": "/sobre",
"dest": "/api/index.py"
},
{
"src": "/portfolio",
"dest": "/api/index.py"
},
{
"src": "/api/cervejas",
"dest": "/api/index.py"
},
{
"src": "/api/livros",
"dest": "/api/index.py"
}
]
}
Meio grande? Também achei.
Notou que em "routes" a chave "dest" se repete? Então vamos reduzir esse bagunça para algo mais legível
{
"version": 2,
"builds": [
{
"src": "api/index.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "/api/index.py"
}
]
}
Após isso, basta usar a CLI da Vercel. Veja as opções disponíveis com vercel --help
Vamos testar localmente (afinal, não queremos fazer deploy de algo que não funciona)
vercel dev
A saída com comando deverá ser algo como
Vercel CLI 22.0.1
? Set up and deploy “~/vercel-flask-app”? [Y/n] y
? Which scope do you want to deploy to? cauachagas
? Link to existing project? [y/N] n
? What’s your project’s name? vercel-flask-app
? In which directory is your code located? ./
Installing required dependencies...
> Building @vercel/python:api/index.py
Installing required dependencies...
> Built @vercel/python:api/index.py [14s]
E ao final, ele dá acesso ao http://localhost:3000
Para fazer o deploy da aplicação
vercel
Para produção
vercel --prod
Em todos os casos, ele mostrará um link para acessar sua aplicação.
OBS: Não estou falando sobre variáveis de ambiente. Mais caso precise, utilize o site da vercel
para expor as variáveis de ambiente que sua aplicação necessita.
Se quiser acessar a aplicação