# Deploy em VPS pelo painel Coolify (recurso do tipo "Docker Compose"). # # ANTES do primeiro deploy, ponha os dados do cliente em um caminho FIXO do # host, FORA da pasta que o Coolify clona — ele re-clona a cada deploy, e # clientes/ está no .gitignore, então o clone nunca traz esses dados: # # scp -r clientes/ usuario@vps:/dados/exporta-sd/clientes # # Não precisa de chown manual: o entrypoint.sh da imagem roda como root no # início do container e ajusta o dono do volume para o usuário `sd` antes de # derrubar privilégio e subir o gunicorn — ver entrypoint.sh e o ENTRYPOINT # no Dockerfile. (Uma reconsequência: cada `scp` novo devolve os arquivos ao # usuário do ssh no host; some sozinho no próximo restart do container.) # Depois, no Coolify → Environment Variables, aponte o volume para lá: # # CLIENTES_DIR=/dados/exporta-sd/clientes # DERIVADOS_DIR=/dados/exporta-sd/_derivados # só se usar a linha de comando # # Sem essas variáveis, o padrão ./clientes cai dentro da pasta do clone, o # compose cria o diretório VAZIO sem avisar e o primeiro upload morre com # "Arquivo canônico ausente". # # Resto do painel: porta exposta 5000, réplicas 1 (ver o comentário de -w 1 no # Dockerfile), e o domínio o Coolify publica via Traefik. services: exporta-sd: build: context: . dockerfile: Dockerfile # 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" environment: PORT: "5000" 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. Sem esta montagem, a tela inicial abre # e o primeiro upload falha com "Arquivo canônico ausente". - ${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