# LLMSwapper en contenedor. # # docker compose up -d y abre http://127.0.0.1:7373 # # Antes de usarlo, lee "Docker" en el README: dentro de un contenedor el panel pierde la # detección de procesos y los targets de WSL, y en macOS solo puede tocar las credenciales si # están en fichero y no en el Llavero. No es un bug, es la frontera del contenedor. # # NO LEVANTES ESTO Y `node server.js` A LA VEZ. El suelo que mantiene la app dentro del cupo del # endpoint de uso (unas 5 peticiones por 5 minutos) se lleva POR PROCESO, así que dos instancias # doblan el ritmo de salida y se rate-limitan la una a la otra. Una u otra, no las dos. services: llmswapper: build: . image: llmswapper:latest # Reconstruye en cada `up`. Sin esto, tras un `git pull`, `docker compose up -d` arranca la # imagen ANTERIOR sin avisar y el arreglo que acabas de bajar no corre. Con caché tarda un # par de segundos; no hay npm install que repetir. pull_policy: build container_name: llmswapper # 127.0.0.1: en el lado del HOST. El servidor escucha en 0.0.0.0 dentro del contenedor # porque no le queda otra, así que el loopback tiene que imponerse aquí. Quitar el # "127.0.0.1:" publicaría en todas las interfaces de la máquina un panel que maneja # credenciales de pago; no lo hagas para "verlo desde el móvil". ports: - "127.0.0.1:${SWAPPER_PORT:-7373}:7373" environment: PORT: 7373 SWAPPER_BIND: 0.0.0.0 SWAPPER_IN_CONTAINER: "1" NO_OPEN: "1" volumes: # Las cuentas guardadas y la caché de uso, compartidas con una instalación local del # repo. Es lo que se quiere casi siempre: das de alta una cuenta con `node server.js` y # el contenedor la ve, y al revés. Un volumen con nombre (`llmswapper-data:/app/data`) # daría un almacén SEPARADO y vacío - correcto para un servidor que solo usa Docker, # desconcertante en una máquina donde ya tenías cuentas dadas de alta. # # En un host Linux, CREA data/ antes del primer `up` (`mkdir -p data`; `node server.js` ya # lo hizo si arrancaste el panel alguna vez). Docker crea un origen de bind mount que no # existe como root, y el servidor corre como uid 1000: EACCES al arrancar (mkdir /app/data/backups). El chown # del Dockerfile no ayuda aquí, solo siembra volúmenes con nombre. - ./data:/app/data # La configuración REAL de Claude Code en tu máquina: sin esto el swap no tiene nada que # cambiar y el panel queda en modo mirón. CLAUDE_HOME por defecto es $HOME, que resuelve # solo en Linux y macOS; en Windows (PowerShell) define antes: # $env:CLAUDE_HOME = $env:USERPROFILE # # Se monta el directorio home ENTERO, no ~/.claude y ~/.claude.json por separado, porque # ~/.claude.json va suelto en el home y Claude Code lo reescribe creando un fichero nuevo y # renombrándolo encima: en Linux nativo un bind mount de UN fichero se queda con el inode # viejo, el contenedor lee una copia congelada y sus escrituras nunca llegan al host. Con el # directorio montado el rename ocurre dentro del mount y todo sigue siendo atómico. El # contenedor ve todo tu home; ya tenía tus credenciales de Claude, que es lo valioso. # # Solo en Docker Desktop (Windows, macOS), que resuelve por ruta y no por inode, puedes # cambiar esta línea por las dos de siempre y exponer menos: # - ${CLAUDE_HOME:-${HOME}}/.claude:/home/node/.claude # - ${CLAUDE_HOME:-${HOME}}/.claude.json:/home/node/.claude.json - ${CLAUDE_HOME:-${HOME}}:/home/node restart: unless-stopped