# Deploy da Exportação da SD — a imagem é a do Dockerfile; este arquivo é UM dos # dois jeitos de subi-la no Coolify, e serve também para rodar local. # # ── MODO 1 · Application (Dockerfile) — o que está em produção (2026-09-04) ── # # Neste modo o Coolify IGNORA este arquivo por completo: builda o Dockerfile e # configura tudo pela interface. O que o volume e as variáveis daqui dizem tem # de ser reproduzido lá: # # Persistent storage → Add mount → "Directory mount" # Source Path: /data/coolify/applications//clientes # (o próprio Coolify sugere esse caminho; ele sobrevive # a redeploy — é a pasta de storage da app, não o clone) # Destination Path: /app/clientes # Mesmo esquema para _derivados, só se for usar a linha de comando. # # Dados: a pasta do host nasce VAZIA. Copie o conteúdo para dentro dela — # aponte para "ses-mg", não para "clientes", ou o nível duplica # (.../clientes/clientes/ses-mg): # # scp -r "D:/Exporta-SD/clientes/ses-mg" usuario@vps:/data/coolify/applications//clientes/ # # e confira no host: ls /data/coolify/applications//clientes/ses-mg/contrato/ # Tem de listar itens.yaml E linhas-os.yaml — sem o segundo, o fallback da # linha de OS desliga e `linha_os` vira pendência só no VPS. # # Variáveis: aba Environment Variables (nomes e defaults em .env.example). # Réplicas: 1 (ver o comentário de -w 1 no Dockerfile). # # ── MODO 2 · Docker Compose (ou local) ────────────────────────────────────── # # O Coolify lê este arquivo. Ponha os dados num caminho fixo do host, fora da # pasta que ele clona, e aponte CLIENTES_DIR para lá (Environment Variables no # Coolify, ou um .env ao lado deste arquivo — copie .env.example). Sem a # variável, o padrão ./clientes cai dentro do clone, o compose cria o # diretório VAZIO sem avisar e o primeiro upload morre com "Arquivo canônico # ausente". # # Nos dois modos não há chown manual: o entrypoint.sh roda como root ao subir # o container, ajusta o dono do volume para o usuário `sd` e só então derruba # privilégio e inicia o gunicorn. Um scp novo devolve os arquivos ao usuário do # ssh; resolve sozinho no próximo restart. services: exporta-sd: build: context: . dockerfile: Dockerfile image: exporta-sd:local # Sem `ports:` de propósito: no Coolify o Traefik alcança o container pela # rede interna. `expose` publica a porta só para dentro dessa rede. # Para rodar fora do Coolify, troque por: ports: ["5000:5000"]. expose: - "5000" # Só ESPELHA os defaults do Dockerfile — o valor de verdade mora lá (ENV e # ${VAR:-default} no CMD), porque no Modo 1 este bloco nem é lido. Aqui a # única função é deixar o operador trocar pelo .env sem editar YAML. environment: PORT: ${PORT:-5000} TZ: ${TZ:-America/Sao_Paulo} GUNICORN_TIMEOUT: ${GUNICORN_TIMEOUT:-120} GUNICORN_LOG_LEVEL: ${GUNICORN_LOG_LEVEL:-info} volumes: # OBRIGATÓRIO. O app lê clientes/ses-mg/contrato/itens.yaml a cada # análise (e contrato/linhas-os.yaml, se existir, como fallback da linha # de OS) e grava SD.md em clientes/ses-mg/projetos/. O caminho no # container é fixo: caminhos.py resolve clientes/ a partir da raiz do # código, que é o WORKDIR /app. - ${CLIENTES_DIR:-./clientes}:/app/clientes # Saída da linha de comando (exporta_sd.py --dir _derivados/export). # A aplicação web entrega o JSON pelo download, não por aqui. - ${DERIVADOS_DIR:-./_derivados}:/app/_derivados restart: unless-stopped # Uma SD por vez, em memória de processo: reiniciar descarta a sessão # aberta (o SD.md de origem no volume fica intacto). stop_grace_period: 10s