Como criar API endpoint com Flask: tutorial completo com deploy em Docker

Aprenda como transformar um script Python em um microserviço funcional utilizando Flask e Docker

Neste tutorial, vamos explorar como transformar um script Python em um microserviço funcional utilizando Flask e Docker. Especificamente, vamos criar uma API endpoint que recebe dados JSON e os processa para gerar documentos PDF, demonstrando na prática como containerizar aplicações Python.

Por que criar APIs com Flask e Docker?

Flask é um framework web WSGI (Web Server Gateway Interface) leve e flexível, projetado para facilitar o desenvolvimento rápido de aplicações web escaláveis. Quando combinado com Docker, você obtém um ambiente consistente e portátil que simplifica o deploy e a manutenção de microserviços.

Docker ajuda desenvolvedores a construir, compartilhar e executar aplicações em qualquer lugar, eliminando problemas de configuração de ambiente e gerenciamento complexo de dependências.

Configurando o ambiente Flask

Primeiro, vamos configurar o Flask dentro de um ambiente virtual Python. Se você já possui um ambiente virtual configurado, ative-o e instale o Flask:

$ source venv/bin/activate
venv $ pip install flask

Criando o primeiro endpoint

Vamos começar com um exemplo básico. Crie um arquivo app.py:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hey Invoice Generation App!'

if __name__ == "__main__":
    app.run(debug=True)

Execute o servidor Flask:

venv $ python -m flask run
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment.
 * Running on http://127.0.0.1:5000

Para verificar se tudo está funcionando corretamente, abra seu navegador em http://127.0.0.1:5000 ou execute:

$ curl http://127.0.0.1:5000/
Hey Invoice Generation App!

No console Python, você verá a requisição recebida:

 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [19/Nov/2024 06:09:23] "GET / HTTP/1.1" 200 -

Criando endpoint para geração de PDF

Agora vamos criar um endpoint mais funcional que recebe dados JSON e os processa para gerar documentos PDF:

import invoice
from flask import Flask, jsonify, request, json

app = Flask(__name__)

@app.route("/invoice", methods=["POST"])
def generate_invoice():
    
    if request.is_json:
        data = request.json
    else:
        data = json.loads(request.data)
    
    invoice.generate(data)
    return jsonify({'message': 'Invoice Generated'}), 204

Funcionamento do endpoint

Este método implementa as seguintes funcionalidades:

  • Cria um endpoint no recurso /invoice

  • Aceita apenas requisições POST

  • Valida que o corpo da requisição contém dados JSON

  • Envia os dados para o script gerador de PDF

  • Retorna código HTTP 204 (conteúdo criado) com mensagem JSON

Para testar, reinicie o servidor e envie uma requisição POST:

curl --request POST \
  --url http://127.0.0.1:5000/invoice \
  --header 'Content-Type: application/json' \
  --data "@sample/payload.json"

O documento PDF será gerado na pasta /resources/pdf.

Containerizando a aplicação com Docker

Docker permite executar sua aplicação em qualquer ambiente sem preocupações com configurações específicas do sistema operacional.

Criando o Dockerfile

O Dockerfile é um arquivo de texto com instruções para construir imagens Docker. Vamos criar um partindo de uma imagem Python existente:

FROM python:3.11-slim-buster

WORKDIR /app

RUN apt-get update && apt-get install -y wget xfonts-75dpi fontconfig libjpeg62-turbo libx11-6 libxcb1 libxext6 libxrender1 xfonts-base
RUN wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb \
    && dpkg -i wkhtmltox_0.12.6-1.buster_amd64.deb \
    && apt --fix-broken install

COPY ./requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY ./ .

EXPOSE 5001

CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0", "--port=5001"]

Estrutura do Dockerfile explicada

Instrução

Função

FROM

Define a imagem base (Python 3.11)

WORKDIR

Define o diretório de trabalho

RUN

Executa comandos durante o build

COPY

Copia arquivos para a imagem

EXPOSE

Documenta a porta utilizada

CMD

Define o comando de inicialização

Gerando requirements.txt

Antes de construir a imagem, crie o arquivo de dependências:

venv $ pip freeze > requirements.txt

Deploy local com Docker

Construindo a imagem

Execute o comando build para criar a imagem Docker:

$ docker build . --tag 'invoice-generator'
[+] Building 3.0s (13/13) FINISHED                                   docker:desktop-linux
 => [internal] load build definition from Dockerfile                                 0.0s
 ...

Verifique se a imagem foi criada:

$ docker image list
REPOSITORY                 TAG       IMAGE ID       CREATED              SIZE
invoice-generator          latest    xxxxxxxxxxxx   xxxxxxxx             330MB

Executando o container

Para iniciar uma instância do container, execute:

$ docker run -it -p 5001:5001 invoice-generator
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5001
 * Running on http://172.17.0.2:5001
Press CTRL+C to quit

A opção -p 5001:5001 vincula a porta 5001 do container à porta 5001 do host, permitindo que o container receba requisições externas.

Testando a aplicação containerizada

Verifique se tudo está funcionando:

$ curl http://127.0.0.1:5001/
Hey Invoice Generation App!

Perguntas frequentes sobre Flask API e Docker

Como escolher entre Flask e Django para APIs?
Flask é ideal para microserviços e APIs leves devido à sua simplicidade e flexibilidade. Django é mais adequado para aplicações complexas com muitas funcionalidades built-in.

Preciso usar Docker para deploy de APIs Flask?
Não é obrigatório, mas Docker oferece consistência entre ambientes de desenvolvimento e produção, facilitando o deploy e escalabilidade.

Como adicionar autenticação à minha Flask API?
Você pode usar extensões como Flask-JWT-Extended para implementar autenticação baseada em tokens JWT.

Qual a diferença entre EXPOSE e -p no Docker?
EXPOSE documenta qual porta o container usa, mas não mapeia portas. A opção -p no docker run efetivamente vincula portas do container ao host.

Próximos passos

Agora que você transformou um script Python em um microserviço completo, considere:

  • Implementar tratamento de erros mais robusto

  • Adicionar autenticação e autorização

  • Configurar logging adequado

  • Implementar testes automatizados

  • Usar Docker Compose para orquestração de múltiplos containers

  • Implementar CI/CD para automação de deploy

Este tutorial demonstrou como criar uma API REST funcional com Flask e containerizá-la usando Docker, transformando scripts Python em microserviços profissionais prontos para produção. A combinação de Flask e Docker oferece uma base sólida para desenvolvimento de aplicações modernas e escaláveis.