Files
Exporta-SD/docker-compose.yml
T
wanderandClaude Sonnet 5 4ef1a7a4c8 Corrige permissão do volume de clientes/ via entrypoint, não build
RUN chown no Dockerfile só atinge a imagem: o bind mount de clientes/
substitui o diretório (dono incluído) ao subir o container, apagando
qualquer chown feito em build. entrypoint.sh roda como root no início do
container, ajusta o dono do volume recém-montado e derruba privilégio
para o usuário sd (via gosu) antes do gunicorn.

.gitattributes fixa LF em *.sh: autocrlf do Git no Windows senão
reescreveria o script para CRLF, quebrando o shebang dentro do container.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 14:32:01 -03:00

52 lines
2.4 KiB
YAML

# 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 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