# ============================================================================== # OpenClaw Gateway para Hugging Face Spaces # Base: node:20-slim (LTS, estável, auditado) # Estratégia: Gateway HTTP que roteia para OpenClaw.ai API + ferramentas locais # Arquitetura: Stateless, Zero-disk, Máximo desempenho no Free Tier # ============================================================================== FROM node:20-slim # ------------------------------------------------------------------------------ # BLOCO 1: ROOT - Dependências auditadas ao mínimo necessário # Cada pacote justificado: # curl: health checks e chamadas HTTP internas # ca-certificates: validação SSL/TLS para APIs externas (CRÍTICO) # tini: gerenciamento de processos PID 1 (anti-zumbi) # tzdata: fuso horário correto nos logs # ------------------------------------------------------------------------------ USER root ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update \ && apt-get install -y --no-install-recommends \ curl \ ca-certificates \ tini \ tzdata \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean # ------------------------------------------------------------------------------ # BLOCO 2: USUÁRIO - UID 1000 mandatório para Hugging Face # Criamos o usuário com home explícito e UID/GID fixos. # Isso evita o erro "user not found" que ocorre quando apenas USER 1000 é usado # sem o useradd correspondente. # ------------------------------------------------------------------------------ RUN groupadd --gid 1000 appuser \ && useradd \ --uid 1000 \ --gid 1000 \ --create-home \ --shell /bin/bash \ appuser # Cria diretórios de trabalho com permissões corretas ANTES de trocar usuário RUN mkdir -p /app /app/logs \ && chown -R appuser:appuser /app # Troca para usuário não-root - toda operação daqui em diante é segura USER appuser WORKDIR /app # ------------------------------------------------------------------------------ # BLOCO 3: NODE.JS SETUP - npm global configurado para o usuário sem root # Configuramos o prefix do npm para o home do usuário para que instalações # globais não exijam sudo e funcionem corretamente no PATH. # ------------------------------------------------------------------------------ ENV NPM_CONFIG_PREFIX=/home/appuser/.npm-global ENV PATH="/home/appuser/.npm-global/bin:${PATH}" # Cria o diretório global do npm antes de usar RUN mkdir -p /home/appuser/.npm-global # ------------------------------------------------------------------------------ # BLOCO 4: DEPENDÊNCIAS DA APLICAÇÃO # Instalamos pacotes que compõem o gateway: # express: servidor HTTP leve e battle-tested # http-proxy-middleware: proxy para API do OpenClaw.ai # node-fetch: chamadas HTTP modernas # dotenv: carregamento de variáveis de ambiente # Usamos npm ci equivalente com versões fixas para builds reproduzíveis. # ------------------------------------------------------------------------------ COPY --chown=appuser:appuser package.json ./ RUN npm install --omit=dev --no-audit --no-fund \ && npm cache clean --force # ------------------------------------------------------------------------------ # BLOCO 5: CÓDIGO DA APLICAÇÃO # O servidor gateway é copiado após npm install para aproveitar cache de layers. # Mudanças no código não re-executam o npm install (otimização de build time). # ------------------------------------------------------------------------------ COPY --chown=appuser:appuser server.js ./ COPY --chown=appuser:appuser entrypoint.sh ./ RUN chmod +x /app/entrypoint.sh # ------------------------------------------------------------------------------ # BLOCO 6: VARIÁVEIS DE AMBIENTE # ------------------------------------------------------------------------------ ENV PORT=7860 ENV HOST=0.0.0.0 ENV NODE_ENV=production # Memória: 4GB seguro para HF Free Tier # --expose-gc: permite garbage collection manual quando necessário ENV NODE_OPTIONS="--max-old-space-size=4096 --expose-gc" # OpenClaw configurações # INSTRUÇÃO: Adicione como Secrets no painel do HF Space ENV OPENCLAW_API_KEY="" ENV OPENCLAW_BASE_URL="https://api.openclaw.ai" # Integrações de IA gratuitas ENV OPENROUTER_API_KEY="" ENV GEMINI_API_KEY="" ENV GROQ_API_KEY="" # Telemetria desabilitada ENV OPENCLAW_TELEMETRY=false # Fuso horário ENV TZ="America/Sao_Paulo" EXPOSE 7860 # ------------------------------------------------------------------------------ # BLOCO 7: HEALTHCHECK # Verifica se o servidor está respondendo a cada 30 segundos. # 3 falhas consecutivas = container considerado unhealthy pelo orchestrador. # Timeout de 10s evita falsos positivos em inicializações lentas. # ------------------------------------------------------------------------------ HEALTHCHECK \ --interval=30s \ --timeout=10s \ --start-period=30s \ --retries=3 \ CMD curl -f http://localhost:7860/health || exit 1 # tini como PID 1 garante propagação correta de sinais ENTRYPOINT ["/usr/bin/tini", "--"] CMD ["/app/entrypoint.sh"]