Ctrl K
ComunidadGuías…

docker-compose.yml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# 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