Inteligência artificial, sem ruído.
Tutoriais9 min

Seu modelo de machine learning não está pronto até outra pessoa conseguir chamá-lo

Guia prático para tirar um modelo de churn do notebook: Docker, FastAPI e AWS EC2 — com três falhas de deploy que ninguém avisa.

Seu modelo de machine learning não está pronto até outra pessoa conseguir chamá-lo

Por que “funciona no meu notebook” não basta

Existe um ponto em que todo projeto de machine learning deixa de ser um experimento e precisa virar um serviço. É o momento em que o modelo que você treinou — e que responde perfeitamente no Swagger UI do seu laptop — precisa sobreviver a um desconhecido digitando uma URL do outro lado do mundo. Se ele morre quando a tela do notebook dorme, ele ainda não é um produto. É um brinquedo que só você pode usar.

Essa é exatamente a transição que este guia percorre. O ponto de partida é uma API FastAPI de previsão de churn (a probabilidade de um cliente cancelar): você envia os dados de um cliente e recebe de volta uma probabilidade, uma previsão e um nível de risco. O modelo usa um pipeline do scikit-learn (escalador + classificador) já treinado. E o caminho até “alguém consegue chamá-lo” passa por containerização com Docker, um servidor na AWS e três falhas que ninguém avisa.

Em 2026, com a maturidade do MLOps, o básico mudou: entregar código não é mais suficiente — você entrega um ambiente. A boa notícia é que o custo de fazer isso direito caiu drasticamente. Uma instância de nível gratuito é tudo o que este projeto precisa.

O que você ganha (e o que não ganha)

✅ O que você ganha

  • Um modelo acessível por qualquer pessoa com o endereço IP, não só por você no seu computador.
  • Reprodutibilidade total: as mesmas versões de Python e de pacotes rodam no seu laptop e no servidor.
  • Um endereço estável (Elastic IP) que não muda quando a máquina reinicia.
  • Entendimento real dos erros de infraestrutura — que são a maioria dos problemas reais de deploy.
  • Base pronta para evoluir para um app de machine learning completo na nuvem.

⚠️ O que você NÃO ganha

  • HTTPS: tudo roda em HTTP simples na porta 8000, aceitável para aprendizado, insuficiente para dados reais de clientes.
  • Autenticação: qualquer pessoa com o IP consegue chamar o endpoint — sem API key, sem rate limiting.
  • Auto-recuperação: se a AWS reiniciar o hardware, a API fica fora do ar até você reiniciá-la manualmente.

Requisitos

ComponenteMínimoRecomendadoIdeal
ModeloPipeline scikit-learn já treinadoSalvo com joblib/pickleVersionado com metadados de treino
ServidorQualquer máquina com DockerEC2 t3.micro (Ubuntu)Free tier + Elastic IP
ConhecimentoPython básicoFastAPI + linha de comandoNoções de rede e grupos de segurança
Tempo estimado2 horas1 hora45 minutos
Pré-requisitos para colocar o modelo no ar, com suporte a Linux, macOS e Windows (tudo roda via terminal e console AWS).

Passo 1 — Congele o ambiente antes de qualquer coisa

O erro mais comum em deploy é deixar o pip instalar “o que for mais recente” dentro do container. O resultado: o modelo funciona no seu laptop e quebra no servidor, porque as versões divergiram. A solução é congelar o ambiente com pip freeze, que lista as versões exatas dos pacotes que você realmente está usando:

fastapi==0.141.1
uvicorn[standard]==0.40.0
scikit-learn==1.9.0
pandas==3.0.3
numpy==2.4.6
pydantic==2.13.4
joblib==1.5.3

Um detalhe que passa despercebido: se você roda Python 3.14 localmente (uma versão recente), não use a imagem base python:3.11-slim por hábito. Use a imagem que espelha seu ambiente — python:3.14-slim — para o container se comportar o mais próximo possível da sua máquina.

Passo 2 — Escreva o Dockerfile (e o erro que quebrou tudo)

FROM python:3.14-slim
WORKDIR /code
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY ./app ./app
COPY ./models ./models
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

O build em si passou, mas na primeira execução veio o erro que ninguém espera: ModuleNotFoundError: No module named 'schemas'. A causa é sutil. Localmente você sempre rodava uvicorn main:app de dentro da pasta app/, então o schemas.py ficava ao lado e era encontrado. No Dockerfile, o CMD roda uvicorn app.main:app a partir de /code, o que faz o Python tratar app como um pacote — e o diretório de trabalho diferente é o suficiente para quebrar a importação.

A correção é simples: diga ao Uvicorn para carregar o app usando a pasta app como raiz, imitando como você já rodava antes:

CMD ["uvicorn", "main:app", "--app-dir", "app", "--host", "0.0.0.0", "--port", "8000"]

Verificação intermediária: reconstrua a imagem, suba o container e envie uma requisição de teste. A resposta deve trazer exatamente a mesma probabilidade, previsão e nível de risco da Parte A — se bateu, o container não alterou o comportamento do modelo.

Passo 3 — Suba a instância EC2

O guia usa uma instância t3.micro com Ubuntu, elegível para o nível gratuito da AWS — ideal para uma API FastAPI com um único modelo. Dois pontos de configuração fazem diferença:

  • Grupo de segurança: crie duas regras de entrada — SSH na porta 22 (restrita ao seu IP) e uma regra TCP personalizada na porta 8000 (aberta a todos, pois é onde a API será exposta).
  • Usuário IAM em vez de root: operar direto da conta root não tem limites de acesso; um usuário IAM faz o mesmo trabalho com um raio de dano muito menor se algo der errado.

Passo 4 — Instale o Docker e envie o projeto

Depois de acessar a instância via SSH, instale o Docker:

sudo apt update
sudo apt install -y docker.io
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker $USER

Em vez de subir a imagem para o Amazon ECR, o guia copia os arquivos do projeto via scp e reconstrói a imagem direto na instância — mais simples para um projeto pequeno. Foi aí que apareceu a segunda falha:

ssh: connect to host <ip> port 22: Connection timed out

O instinto é culpar a instância. O problema real era a regra de firewall do grupo de segurança, que restringia o SSH ao seu IP — e o seu IP havia mudado desde a configuração. Atualizar a regra resolveu na hora. É um tropeço comum e rápido de diagnosticar, mas que trava o deploy se você não souber onde olhar.

Passo 5 — Rode o container em produção

Com os arquivos transferidos, reconstrua a imagem (o mesmo comando que você rodou localmente) e suba o container:

docker build -t churn-api .
docker run -d -p 8000:8000 churn-api

O -d é o que importa aqui: ele mantém o container rodando em segundo plano e desacoplado da sua sessão SSH. Sem ele, o container morre no instante em que você desconecta — o que destruiria todo o propósito. Teste acessando http://<ip-público>:8000/docs no seu navegador e envie o mesmo cliente de teste pelo /predict. Se os valores baterem com os locais, alguém em qualquer lugar do mundo agora consegue chamar o seu modelo.

Passo 6 — Prenda o endereço com um Elastic IP

O IP público padrão do EC2 não é garantido: ele muda quando a instância para e reinicia. Anexar um Elastic IP fixa o endereço, garantindo que ele permaneça o mesmo mesmo após reiniciar o servidor. É um passo rápido que transforma o deploy de “prova de conceito” em algo minimamente estável.

O que ainda falta para produção de verdade

O guia é honesto sobre o que não resolveu: não há HTTPS (tudo em HTTP simples), não há autenticação (qualquer um com o IP pode chamar /predict) e não há reinício automático do container se a instância reiniciar. Nenhum desses problemas é difícil — mas deixá-los de fora, em vez de fingir completude, é o que separa um guia confiável de um artigo enganoso.

Troubleshooting

  • ModuleNotFoundError: No module named 'schemas' dentro do container → O diretório de trabalho mudou (o app é tratado como pacote). Solução: use CMD ["uvicorn", "main:app", "--app-dir", "app", ...].
  • ssh: connect to host port 22: Connection timed out → A regra de SSH do grupo de segurança restringe ao seu IP antigo. Solução: atualize o IP de origem na regra da porta 22.
  • ❌ O container morre ao fechar a sessão SSH → Faltou o -d no docker run. Solução: rode com docker run -d -p 8000:8000.
  • ❌ O IP público mudou e a API ficou inacessível → O IP padrão do EC2 não é fixo. Solução: anexe um Elastic IP.
  • ❌ O build no servidor é muito mais lento que no laptop → A t3.micro tem menos CPU para compilar pacotes. Solução: aceite o tempo maior ou use imagens pré-construídas (wheels) sempre que possível.
  • ❌ Versões de pacote divergem entre local e servidor → Você não congelou o ambiente. Solução: gere o requirements.txt com pip freeze antes de escrever o Dockerfile.

Perguntas frequentes

Preciso de um servidor pago para isso? Não. Uma instância t3.micro é elegível para o nível gratuito da AWS nos primeiros 12 meses, o suficiente para uma API de um único modelo.

Por que Docker e não só copiar o código? Porque o código carrega dependências implícitas — versão de Python, caminhos de arquivos, bibliotecas. O Docker empacota tudo isso num ambiente autossuficiente que roda em qualquer máquina.

Por que o modelo quebrou se o build não deu erro? O build só verifica se as dependências instalaram, não se o app carrega corretamente no diretório de trabalho do container. Erros de importação só aparecem na execução.

O endpoint já está seguro? Não. Falta HTTPS e autenticação — sem isso, qualquer pessoa com o IP consegue chamá-lo. Aceitável para aprendizado, não para dados reais.

O que é Elastic IP e por que preciso dele? É um endereço fixo da AWS. O IP público padrão muda a cada parada/reinício; o Elastic IP o mantém estável.

Para onde isso vai

O percurso — notebook → API local → API containerizada → serviço acessível pela internet — encapsula a diferença fundamental entre escrever código e colocar machine learning em produção. A lição mais valiosa não é técnica: a maioria dos problemas de deploy não está na lógica do modelo, mas em incompatibilidades de ambiente e mudanças sutis de infraestrutura. O próximo passo natural é aplicar essa mesma visão a um modelo maior que um serviço de endpoint único — e é exatamente aí que o que você aprendeu aqui vira base.


Descubra mais sobre noticiAI

Assine para receber nossas notícias mais recentes por e-mail.

R
Sobre o autorRedação Noticiai

Equipe editorial dedicada a explicar inteligência artificial com clareza, independência e contexto.