| # ============================================================================== | |
| # 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"] |