Skip to main content

Executando um app online

Neste tutorial, você vai criar um Data App com uma API simples: ao receber uma requisição, ela responde “Olá, Data Apps!”. Depois, você muda essa mensagem e reinicia o serviço para conferir o resultado.

Diferentemente do batch, que processa um lote e termina, o processo online permanece disponível para receber requisições HTTP. Você pode usá-lo para APIs, consultas e integrações que precisam de uma resposta na hora.

O exemplo usa Python, Flask e Gunicorn. O Flask define as rotas; o Gunicorn mantém o servidor que recebe as requisições. Você também pode usar Node.js ou outra linguagem, empacotando o servidor em uma imagem Docker.

Ambiente e recursos do exemplo​

Reutilize a tenant de desenvolvimento dos outros guias e crie um app separado. O exercício não lê nem grava dados da tenant.

RecursoValor no exemplo
AppGuia de app online, Name guiaonlinedemo, versão 0.1.0
Processoonline_demo
Imagemguide-online:1.0.0
Porta8080
Healthcheck/healthz
Máquina de execuçãoc1.pico — 0,25 vCPU e 250 MiB
CódigoExemplo completo nos samples

Etapas do tutorial​

  1. Prepare os arquivos
  2. Construa a imagem
  3. Inicie o serviço
  4. Teste e confira os logs

Enviar o manifesto, construir a imagem e iniciar o processo são operações distintas. O build prepara a imagem; o serviço precisa ser iniciado depois.

Passo 1: Prepare os arquivos​

ArquivoPara que serve
app.pyImplementa a mensagem e o healthcheck
gunicorn.conf.pyConfigura porta, workers e logs do servidor
requirements.txtDefine as versões de Flask e Gunicorn
DockerfileEmpacota e inicia a aplicação
manifest.jsonDefine imagem, porta, healthcheck e recursos na plataforma

O exemplo usa Python 3.14. Clone o repositório e execute a partir da pasta do exemplo:

git clone --branch master https://github.com/totvslabs/carolapp-samples.git
cd carolapp-samples/guides/data-apps/first-online
python3.14 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
gunicorn --config gunicorn.conf.py app:app

Abra localhost:8080 no navegador. O resultado esperado é:

{"message": "Olá, Data Apps!"}

Resposta da API no navegador durante o teste local

Teste também localhost:8080/healthz:

{"status": "ok"}

O healthcheck é obrigatório: a plataforma valida essa rota para verificar se o serviço está disponível. Implemente /healthz e configure o mesmo caminho no manifesto. Ela deve responder HTTP 200, sem exigir autenticação interna, na porta do processo. Sem uma resposta válida, o serviço não fica disponível.

O servidor continua em execução depois de responder. Para encerrar o teste local, use Ctrl+C no terminal.

Saiba mais: as rotas e o código Python
RequisiçãoResposta
GET /200 com a mensagem definida em GREETING
GET /healthz200 com o estado do servidor
GET /inexistente404: a aplicação está respondendo, mas essa rota não existe
app.py
"""API do guia online: sem dados de negócio nem credenciais."""

import os

from flask import Flask, jsonify

app = Flask(__name__)
app.json.ensure_ascii = False


@app.get("/")
def index():
return jsonify(message=os.environ.get("GREETING", "Olá, Data Apps!"))


@app.get("/healthz")
def health():
return jsonify(status="ok")


@app.errorhandler(404)
def not_found(error):
return jsonify(error="not_found"), 404

O código usa os.environ para ler GREETING. Se a variável não existir, retorna Olá, Data Apps!. Na plataforma, o valor é definido no manifesto.

Esta API apenas responde HTTP; por isso, não precisa de credenciais nem do pyCarol no teste local. O SDK pode ser adicionado quando sua aplicação precisar consultar recursos da tenant ou ler Settings.

Saiba mais: teste local com Docker

Com o Docker em execução, rode os comandos na sua máquina local, na pasta do exemplo:

docker build -t guide-online:1.0.0 .
docker run --rm --name guide-online -p 8080:8080 guide-online:1.0.0

Libere antes a porta 8080, encerrando o teste Python com Ctrl+C. Abra as mesmas URLs no navegador e confira as respostas.

Em -p 8080:8080, o primeiro número é a porta da sua máquina e o segundo é a do contêiner. Esse mapeamento é do teste local; na plataforma, a porta é configurada no manifesto.

Para encerrar, use Ctrl+C. O --rm remove o contêiner quando ele termina; a imagem continua disponível para outros testes.

Saiba mais: o Dockerfile e a inicialização do servidor

O Dockerfile é a receita da imagem, seguindo o padrão do ecossistema Docker. Neste exemplo, ele instala as dependências e inicia o Gunicorn:

Dockerfile
FROM python:3.14-slim

WORKDIR /app

ENV PYTHONUNBUFFERED=1
ENV PORT=8080
ENV LOG_LEVEL=info

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

COPY app.py gunicorn.conf.py ./

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \
CMD python -c "import os, urllib.request; urllib.request.urlopen('http://127.0.0.1:' + os.environ.get('PORT', '8080') + '/healthz', timeout=2)"

ENTRYPOINT ["gunicorn", "--config", "gunicorn.conf.py", "app:app"]
InstruçãoPapel no exemplo
FROMDefine o ambiente Python
ENVConfigura padrões de porta e logs
COPY e RUNIncluem os arquivos e instalam as dependências
EXPOSEDocumenta a porta usada pelo programa
HEALTHCHECKPermite verificar a resposta do contêiner no Docker local
ENTRYPOINTInicia app:app usando a configuração do Gunicorn

app:app significa o objeto app do arquivo app.py. Em gunicorn.conf.py, o servidor escuta em 0.0.0.0, na porta recebida em PORT.

O exemplo usa um worker e duas threads. Dimensione concorrência, memória e timeouts conforme as requisições da sua aplicação. Flask e Gunicorn são projetos open source. Consulte as documentações do Flask e do Gunicorn para adaptar essa configuração.

Saiba mais: manifesto, máquina, escala e healthcheck
manifest.json
{
"online": {
"processes": [
{
"name": "online_demo",
"algorithmName": "online_demo",
"algorithmTitle": {
"pt-BR": "API do guia online",
"en-US": "Online guide API"
},
"algorithmDescription": {
"pt-BR": "Responde a requisições HTTP sem acessar dados de negócio.",
"en-US": "Handles HTTP requests without business data."
},
"instanceProperties": {
"profile": "",
"environments": {
"PORT": "8080",
"GREETING": "Olá, Data Apps!",
"LOG_LEVEL": "info"
},
"properties": {
"dockerName": "guide-online",
"instanceType": "c1.pico",
"preemptible": false,
"port": 8080,
"healthcheck": {
"path": "/healthz"
},
"autoscale": {
"enabled": false,
"minReplicas": 1,
"maxReplicas": 1
}
}
}
}
]
},
"docker": [
{
"dockerName": "guide-online",
"dockerTag": "1.0.0",
"gitRepoUrl": "https://github.com/totvslabs/carolapp-samples",
"gitBranch": "master",
"gitPath": "/guides/data-apps/first-online",
"gitDockerfileName": "Dockerfile"
}
]
}

A porta aparece em dois lugares:

ConfiguraçãoQuem utiliza
environments.PORTO programa, para saber onde escutar
properties.portA plataforma, para encaminhar as requisições ao contêiner

Os dois valores precisam coincidir. O EXPOSE do Dockerfile não substitui essa configuração.

O endereço 0.0.0.0 permite receber as chamadas encaminhadas ao contêiner. localhost e 127.0.0.1 referem-se ao próprio ambiente em que o programa executa; por isso, usamos localhost no navegador e 0.0.0.0 na configuração do servidor.

A plataforma chama o healthcheck periodicamente. Mantenha /healthz rápida; ela não precisa consultar dados de negócio.

A verificação HEALTHCHECK da imagem e o healthcheck.path do manifesto têm a mesma rota, mas são configurações distintas. A instrução do Dockerfile permite testar a imagem localmente; ela não substitui healthcheck.path no manifesto.

Máquina e escala do processo

Estes campos ficam em instanceProperties.properties:

CampoValor no exemploComo funciona
instanceTypec1.picoDefine CPU, memória e preço por hora. A pico oferece 0,25 vCPU e 250 MiB; a máquina do build é escolhida separadamente
preemptiblefalseUsa recursos não interrompíveis. Com true, permite recursos que a infraestrutura pode interromper; a aplicação precisa tolerar essas interrupções
autoscale.enabledfalseDesabilita o ajuste automático da quantidade de réplicas do serviço
autoscale.minReplicas1Define o mínimo de réplicas quando a escala automática está habilitada
autoscale.maxReplicas1Define o máximo de réplicas quando a escala automática está habilitada

Uma réplica é uma cópia em execução do serviço. Com a escala automática habilitada, a plataforma ajusta a quantidade de cópias conforme o uso, respeitando os limites definidos. Por exemplo, enabled: true, minReplicas: 1 e maxReplicas: 3 permitem variar entre uma e três cópias. Isso não altera o tamanho da máquina definido em instanceType.

Neste tutorial, usamos uma única réplica, sem escala automática. Mais réplicas consomem mais recursos e aumentam o custo. Confira a estimativa para uma pico e a referência do manifesto.

Passo 2: Construa a imagem​

  1. Abra Data Apps → Developed Apps → Create new App.
  2. Preencha Label Guia de app online, Name guiaonlinedemo, Version 0.1.0 e uma descrição.
  3. Selecione Customer Tenant em Low Latency Data Source for Servers (MCP/REST) e deixe Unified tenant vazio.
  4. Clique em Create App e aguarde a criação.

Campos preenchidos para criar o app Guia de app online

  1. Em Files → Upload file, escolha manifest.json da pasta do exemplo.
  2. Aguarde o deploy. Confira o arquivo como Monitor Processes e o processo online_demo na aba Process.

Manifesto do app online reconhecido como Monitor Processes na aba Files

  1. Clique em Build e selecione guide-online.
  2. Mantenha a branch master carregada do manifesto, sem editar o campo. O exemplo é público, então o token fica vazio. O campo GitHub Token também aceita a credencial de outros provedores Git compatíveis, como Azure DevOps.
  3. Clique em Next, confira a tag 1.0.0 e escolha c1.small ou c1.medium em Instance type to build docker image → Edit. A orientação operacional é usar esses tamanhos no build pela menor concorrência e pelo pool maior.
  4. Clique em Build image e abra a task criada para acompanhar o resultado.

Build da imagem guide-online com branch master carregada do manifesto

Imagem guide-online na tag 1.0.0 e máquina c1.small selecionada para o build

Resultado esperado: imagem construída com sucesso. Confira os logs da task antes de tentar iniciar o serviço se houver falha.

💡 Dica: preparação demorada​

Se a preparação do aplicativo estiver demorando mais do que o esperado, tente refazer o build com outra instância. Uma opção com mais recursos pode ajudar.

Branch, tags e publicação
  • Branch, tags da imagem e acesso ao Git: confira o guia batch.
  • Publicar e instalar uma versão do app em outro ambiente: siga Antes de começar.

Passo 3: Inicie o serviço​

  1. Abra Process e localize online_demo.
  2. Use Run para iniciar e acompanhe o estado até ficar disponível.
  3. No cabeçalho, abra a URL indicada em Services App.
  4. Confira a mensagem Olá, Data Apps! na rota / e teste também /healthz.

Processo online ativo e URL fornecida pela plataforma em Services App

Mensagem retornada pela API hospedada na plataforma durante a validação do guia

Resultado esperado: processo disponível e respostas das duas rotas conferidas.

Padrão da URL gerada para o app online: https://<tenantname>-<appname>.apps.carol.ai

Validação do exemplo: o serviço iniciou com c1.pico na tenant de desenvolvimento, respondeu à rota / e passou pelo healthcheck /healthz. Esse teste confirma a execução desta API simples; ajuste a máquina conforme a carga da sua aplicação.

A task de inicialização pode aparecer como Complete enquanto o serviço continua ativo; ela registra a operação de iniciar o processo.

O servidor permanece ativo após responder. Cada acesso é uma requisição HTTP; não é necessário clicar em Run para cada chamada.

💡 Dica: inicialização demorada​

Se o aplicativo estiver demorando mais do que o esperado para iniciar, tente executar o processamento novamente com outra instância. Uma opção com mais recursos pode ajudar.

Passo 4: Teste e confira os logs​

Altere a mensagem sem outro build​

  1. No manifesto local, altere GREETING para Olá, guia online!.
  2. Reenvie o manifesto em Files e aguarde o deploy.
  3. Em Process, use Stop, aguarde a parada e depois Run em online_demo.
  4. Acesse a URL novamente e confira a nova mensagem.

API retornando a nova mensagem após atualizar o manifesto e reiniciar com c1.pico

Resultado esperado: a resposta muda sem outro build, pois você alterou apenas a configuração. Uma mudança em código, dependências ou Dockerfile exige construir outra imagem. A diferença entre tag da imagem e versão do app está no guia batch.

Saiba mais: variáveis de ambiente, .env e Docker

Variáveis de ambiente configuram o programa sem alterar seu código. Neste exemplo, GREETING muda a mensagem, PORT define a porta e LOG_LEVEL define o nível dos logs do Gunicorn.

Onde configurarComo funcionaExemplo
Terminal localA variável vale para o comando executadoGREETING="Olá, guia online!" gunicorn --config gunicorn.conf.py app:app
.env localArquivo de configuração, mantido fora do Git; exige carregamento pelo programa ou pela ferramentaGREETING=Olá, guia online!
ENV no DockerfileDefine um valor padrão dentro da imagemENV LOG_LEVEL=info
docker run -eDefine o valor ao iniciar o contêiner, substituindo o padrão da imagem-e LOG_LEVEL=debug
environments no manifestoFornece as variáveis na execução pela plataforma"GREETING": "Olá, guia online!"
Contexto da plataformaIdentifica a tenant, o app e a execução para as integraçõesCAROLTENANT, CAROLAPPNAME, LONGTASKID

Este exemplo não carrega .env automaticamente. Para testá-lo com Docker, crie um .env na pasta do exemplo e forneça o arquivo ao iniciar o contêiner:

docker run --rm --name guide-online --env-file .env -p 8080:8080 guide-online:1.0.0

Para carregar .env ao executar Python diretamente, você pode adicionar python-dotenv, como no guia batch. O arquivo não precisa ser enviado à plataforma e não deve entrar no Git nem na imagem.

As variáveis recebidas na execução substituem os padrões ENV da imagem. Ao alterar o manifesto, reenvie-o e reinicie o processo para aplicar os valores. A configuração do Gunicorn é lida na inicialização.

Preserve as variáveis de contexto fornecidas pela plataforma; não as redefina no manifesto nem imprima o ambiente inteiro nos logs.

ARG serve para parâmetros do build e não se torna automaticamente uma variável do serviço. Use variáveis de execução para valores que precisam mudar entre ambientes.

Saiba mais: Settings e acesso com pyCarol

Settings são parâmetros configurados na aba Settings do app, por ambiente. Eles são consultados pela API e não viram variáveis de ambiente automaticamente. Use-os para opções da aplicação, como um endereço de integração ou um limite de resultados.

A API deste tutorial lê apenas GREETING do ambiente. Se você quiser usar Settings, adicione o pyCarol e faça a leitura explicitamente:

from pycarol import Carol, Apps

carol = Carol()
settings = Apps(carol).get_settings()

Carol() aproveita o contexto de autenticação configurado. Na plataforma, o app recebe esse contexto; para executar localmente com API Key, siga a configuração de autenticação do guia batch. O SDK é open source.

Defina também quando seu programa relê os Settings. Se carregar os valores apenas na inicialização, será necessário reiniciar o serviço após uma mudança.

Saiba mais: secrets para credenciais

Senhas, tokens e chaves de API devem usar secrets. Para solicitar a configuração, abra um chamado pelo formulário da plataforma e selecione Quero reportar um tema que não consta em nenhuma das opções anteriores. Informe a organização, a tenant e o app e solicite a orientação para disponibilizar os valores ao processo.

LocalCuidado
Git e manifestoNão grave credenciais nesses arquivos
DockerfileENV e ARG não são mecanismos para guardar secrets na imagem
SettingsUm campo mascarado na tela não equivale, por si só, a um gerenciador de secrets
LogsNão imprima credenciais, todos os Settings ou todas as variáveis do ambiente
Teste localMantenha o .env fora do Git e use credenciais de desenvolvimento

Separe a configuração de cada ambiente: produção deve usar apenas dados e credenciais de produção, sem depender de recursos do exercício.

Confira os logs​

Em Data Apps → seu app → Logs, procure as mensagens de inicialização do Gunicorn e os acessos às rotas. O exemplo envia o access log e o error log para o console, capturado pela plataforma.

Logs do novo app com requisições GET ao healthcheck e resposta HTTP 200

Para investigar uma execução pelo Task ID, use a consulta da view de logs no Explore. Copie o identificador da execução e retire os hífens antes de aplicar o filtro.

Saiba mais: quando o serviço não responde
SituaçãoO que conferir
O processo não fica disponívelImagem/tag, porta, healthcheck e logs de inicialização
/healthz falhaRota existente, resposta HTTP 200 e porta correta
Apenas uma rota retorna 404Caminho e método da requisição implementados no código
Todas as rotas deixam de responderEstado do processo e logs; confirme que ele está iniciado
A mensagem não mudouManifesto atualizado, ambiente correto e reinício do processo

O healthcheck interno não substitui autenticação e autorização nas rotas de negócio. Este exemplo usa apenas uma mensagem fictícia; adapte os controles de acesso antes de receber dados reais.

Encerre o teste​

Use Stop no processo ao terminar o exercício. O online mantém recursos alocados enquanto está ativo, inclusive quando não recebe requisições.

Saiba mais: máquina, tempo de uso e custo

O tipo de máquina define os recursos e o preço por hora do processo. Escolha instanceType no manifesto conforme a memória, a CPU e a concorrência necessárias. A máquina usada no build é uma alocação separada da que mantém a API funcionando.

Use a calculadora da plataforma com uma pico por 720 horas. Essa estimativa considera uma réplica ligada 24 horas por dia, durante 30 dias. Com duas réplicas durante o mesmo período, informe 1.440 horas. Ajuste a quantidade ao período em que o serviço permanecerá ativo.

Calculadora da plataforma com uma instância c1.pico por 720 horas

Os valores da calculadora são estimativas com preços de referência; consulte a própria página para conferir a base dos valores e os itens incluídos.