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.
| Recurso | Valor no exemplo |
|---|---|
| App | Guia de app online, Name guiaonlinedemo, versão 0.1.0 |
| Processo | online_demo |
| Imagem | guide-online:1.0.0 |
| Porta | 8080 |
| Healthcheck | /healthz |
| Máquina de execução | c1.pico — 0,25 vCPU e 250 MiB |
| Código | Exemplo completo nos samples |
Etapas do tutorial
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
| Arquivo | Para que serve |
|---|---|
app.py | Implementa a mensagem e o healthcheck |
gunicorn.conf.py | Configura porta, workers e logs do servidor |
requirements.txt | Define as versões de Flask e Gunicorn |
Dockerfile | Empacota e inicia a aplicação |
manifest.json | Define 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!"}
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
/healthze 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ção | Resposta |
|---|---|
GET / | 200 com a mensagem definida em GREETING |
GET /healthz | 200 com o estado do servidor |
GET /inexistente | 404: a aplicação está respondendo, mas essa rota não existe |
"""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:
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ção | Papel no exemplo |
|---|---|
FROM | Define o ambiente Python |
ENV | Configura padrões de porta e logs |
COPY e RUN | Incluem os arquivos e instalam as dependências |
EXPOSE | Documenta a porta usada pelo programa |
HEALTHCHECK | Permite verificar a resposta do contêiner no Docker local |
ENTRYPOINT | Inicia 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
{
"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ção | Quem utiliza |
|---|---|
environments.PORT | O programa, para saber onde escutar |
properties.port | A 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:
| Campo | Valor no exemplo | Como funciona |
|---|---|---|
instanceType | c1.pico | Define CPU, memória e preço por hora. A pico oferece 0,25 vCPU e 250 MiB; a máquina do build é escolhida separadamente |
preemptible | false | Usa recursos não interrompíveis. Com true, permite recursos que a infraestrutura pode interromper; a aplicação precisa tolerar essas interrupções |
autoscale.enabled | false | Desabilita o ajuste automático da quantidade de réplicas do serviço |
autoscale.minReplicas | 1 | Define o mínimo de réplicas quando a escala automática está habilitada |
autoscale.maxReplicas | 1 | Define 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
- Abra Data Apps → Developed Apps → Create new App.
- Preencha Label
Guia de app online, Nameguiaonlinedemo, Version0.1.0e uma descrição. - Selecione Customer Tenant em Low Latency Data Source for Servers (MCP/REST) e deixe Unified tenant vazio.
- Clique em Create App e aguarde a criação.

- Em Files → Upload file, escolha
manifest.jsonda pasta do exemplo. - Aguarde o deploy. Confira o arquivo como Monitor Processes e o processo
online_demona aba Process.

- Clique em Build e selecione
guide-online. - Mantenha a branch
mastercarregada 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. - Clique em Next, confira a tag
1.0.0e escolhac1.smallouc1.mediumem Instance type to build docker image → Edit. A orientação operacional é usar esses tamanhos no build pela menor concorrência e pelo pool maior. - Clique em Build image e abra a task criada para acompanhar o resultado.


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 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
- Abra Process e localize
online_demo. - Use Run para iniciar e acompanhe o estado até ficar disponível.
- No cabeçalho, abra a URL indicada em Services App.
- Confira a mensagem
Olá, Data Apps!na rota/e teste também/healthz.

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
- No manifesto local, altere
GREETINGparaOlá, guia online!. - Reenvie o manifesto em Files e aguarde o deploy.
- Em Process, use Stop, aguarde a parada e depois Run em
online_demo. - Acesse a URL novamente e confira a nova mensagem.
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 configurar | Como funciona | Exemplo |
|---|---|---|
| Terminal local | A variável vale para o comando executado | GREETING="Olá, guia online!" gunicorn --config gunicorn.conf.py app:app |
.env local | Arquivo de configuração, mantido fora do Git; exige carregamento pelo programa ou pela ferramenta | GREETING=Olá, guia online! |
ENV no Dockerfile | Define um valor padrão dentro da imagem | ENV LOG_LEVEL=info |
docker run -e | Define o valor ao iniciar o contêiner, substituindo o padrão da imagem | -e LOG_LEVEL=debug |
environments no manifesto | Fornece as variáveis na execução pela plataforma | "GREETING": "Olá, guia online!" |
| Contexto da plataforma | Identifica a tenant, o app e a execução para as integrações | CAROLTENANT, 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.
| Local | Cuidado |
|---|---|
| Git e manifesto | Não grave credenciais nesses arquivos |
| Dockerfile | ENV e ARG não são mecanismos para guardar secrets na imagem |
| Settings | Um campo mascarado na tela não equivale, por si só, a um gerenciador de secrets |
| Logs | Não imprima credenciais, todos os Settings ou todas as variáveis do ambiente |
| Teste local | Mantenha 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.

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ção | O que conferir |
|---|---|
| O processo não fica disponível | Imagem/tag, porta, healthcheck e logs de inicialização |
/healthz falha | Rota existente, resposta HTTP 200 e porta correta |
| Apenas uma rota retorna 404 | Caminho e método da requisição implementados no código |
| Todas as rotas deixam de responder | Estado do processo e logs; confirme que ele está iniciado |
| A mensagem não mudou | Manifesto 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.

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.