Ctrl K
ComunidadGuías…

compose.yaml

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

Archivo original ↗Preguntar a KiBot
name: skillgo

services:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-skillgo}
      POSTGRES_USER: ${POSTGRES_USER:-skillgo}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
    volumes:
      - skillgo-postgres:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
      interval: 5s
      timeout: 3s
      retries: 20
    restart: unless-stopped
    mem_limit: 512m
    cpus: 0.5

  api:
    build:
      context: ./backend
    environment:
      SKILLGO_ENVIRONMENT: production
      SKILLGO_ENVIRONMENT_PREPARATION_ENABLED: ${SKILLGO_ENVIRONMENT_PREPARATION_ENABLED:-false}
      SKILLGO_ENVIRONMENT_BASE_IMAGE: ${SKILLGO_ENVIRONMENT_BASE_IMAGE:-}
      SKILLGO_ENVIRONMENT_QUEUE_WAIT_SECONDS: ${SKILLGO_ENVIRONMENT_QUEUE_WAIT_SECONDS:-3600}
      SKILLGO_DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-skillgo}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-skillgo}
      SKILLGO_STORAGE_ROOT: /var/lib/skillgo/storage
      SKILLGO_DURABLE_CHECKPOINTS_ENABLED: ${SKILLGO_DURABLE_CHECKPOINTS_ENABLED:-false}
      SKILLGO_JWT_SECRET: ${SKILLGO_JWT_SECRET:?set SKILLGO_JWT_SECRET}
      SKILLGO_BOOTSTRAP_EMAIL: ${SKILLGO_BOOTSTRAP_EMAIL:?set SKILLGO_BOOTSTRAP_EMAIL}
      SKILLGO_BOOTSTRAP_PASSWORD: ${SKILLGO_BOOTSTRAP_PASSWORD:?set SKILLGO_BOOTSTRAP_PASSWORD}
      SKILLGO_BOOTSTRAP_NAME: ${SKILLGO_BOOTSTRAP_NAME:-SkillGo Owner}
      SKILLGO_MODEL_BASE_URL: ${SKILLGO_MODEL_BASE_URL:-}
      SKILLGO_MODEL_API_KEY: ${SKILLGO_MODEL_API_KEY:-}
      SKILLGO_MODEL_NAME: ${SKILLGO_MODEL_NAME:-}
      SKILLGO_MODEL_TIMEOUT_SECONDS: ${SKILLGO_MODEL_TIMEOUT_SECONDS:-0}
      SKILLGO_MODEL_CONNECT_TIMEOUT_SECONDS: ${SKILLGO_MODEL_CONNECT_TIMEOUT_SECONDS:-15}
      SKILLGO_MODEL_FIRST_CHUNK_TIMEOUT_SECONDS: ${SKILLGO_MODEL_FIRST_CHUNK_TIMEOUT_SECONDS:-600}
      SKILLGO_MODEL_STREAM_STALL_TIMEOUT_SECONDS: ${SKILLGO_MODEL_STREAM_STALL_TIMEOUT_SECONDS:-600}
      SKILLGO_SKILL_ANALYSIS_TIMEOUT_SECONDS: ${SKILLGO_SKILL_ANALYSIS_TIMEOUT_SECONDS:-45}
      SKILLGO_CONVERSATION_TURN_STALE_SECONDS: ${SKILLGO_CONVERSATION_TURN_STALE_SECONDS:-3600}
      SKILLGO_MODEL_TEMPERATURE: ${SKILLGO_MODEL_TEMPERATURE:-0.2}
      SKILLGO_MODEL_JSON_MODE: ${SKILLGO_MODEL_JSON_MODE:-true}
      SKILLGO_MODEL_NATIVE_TOOLS: ${SKILLGO_MODEL_NATIVE_TOOLS:-true}
      SKILLGO_MODEL_TLS_VERIFY: ${SKILLGO_MODEL_TLS_VERIFY:-true}
      SKILLGO_SANDBOX_WORKER_ENABLED: ${SKILLGO_SANDBOX_WORKER_ENABLED:-false}
      SKILLGO_PLATFORM_DOCUMENT_TOOLS_ENABLED: ${SKILLGO_PLATFORM_DOCUMENT_TOOLS_ENABLED:-false}
      SKILLGO_ARTIFACT_DELIVERY_ONLY: ${SKILLGO_ARTIFACT_DELIVERY_ONLY:-true}
      SKILLGO_CONTEXT_OBSERVABILITY: ${SKILLGO_CONTEXT_OBSERVABILITY:-false}
      SKILLGO_WORKFLOW_AUTO_DELIVERY_VERSION_IDS: ${SKILLGO_WORKFLOW_AUTO_DELIVERY_VERSION_IDS:-}
      SKILLGO_DELIVERY_ONLY_SKILL_IDS: ${SKILLGO_DELIVERY_ONLY_SKILL_IDS:-}
      SKILLGO_AGENT_RUN_SUCCESS_DETAIL_DAYS: ${SKILLGO_AGENT_RUN_SUCCESS_DETAIL_DAYS:-7}
      SKILLGO_AGENT_RUN_FAILURE_DETAIL_DAYS: ${SKILLGO_AGENT_RUN_FAILURE_DETAIL_DAYS:-30}
      SKILLGO_AGENT_RUN_CLEANUP_INTERVAL_SECONDS: ${SKILLGO_AGENT_RUN_CLEANUP_INTERVAL_SECONDS:-3600}
      SKILLGO_STORAGE_RETENTION_DAYS: ${SKILLGO_STORAGE_RETENTION_DAYS:-15}
      SKILLGO_STORAGE_CLEANUP_INTERVAL_SECONDS: ${SKILLGO_STORAGE_CLEANUP_INTERVAL_SECONDS:-3600}
      SKILLGO_STORAGE_ORPHAN_GRACE_HOURS: ${SKILLGO_STORAGE_ORPHAN_GRACE_HOURS:-24}
      SKILLGO_CONTEXT_MAX_MESSAGES: ${SKILLGO_CONTEXT_MAX_MESSAGES:-20}
      SKILLGO_CONTEXT_MAX_CHARS: ${SKILLGO_CONTEXT_MAX_CHARS:-30000}
      SKILLGO_CONVERSATION_LOCK_SECONDS: ${SKILLGO_CONVERSATION_LOCK_SECONDS:-180}
      SKILLGO_WORKSPACE_MAX_FILE_BYTES: ${SKILLGO_WORKSPACE_MAX_FILE_BYTES:-10485760}
      SKILLGO_WORKSPACE_MAX_FILES: ${SKILLGO_WORKSPACE_MAX_FILES:-30}
      SKILLGO_WORKSPACE_EXTRACT_MAX_CHARS: ${SKILLGO_WORKSPACE_EXTRACT_MAX_CHARS:-200000}
      SKILLGO_WORKSPACE_CONTEXT_MAX_CHARS: ${SKILLGO_WORKSPACE_CONTEXT_MAX_CHARS:-40000}
      SKILLGO_CORS_ORIGINS: ${SKILLGO_CORS_ORIGINS:-http://localhost:8080}
      # Skill package upload validation runs in the API.
      SKILLGO_MAX_UPLOAD_BYTES: ${SKILLGO_MAX_UPLOAD_BYTES:-52428800}
      SKILLGO_MAX_UNCOMPRESSED_BYTES: ${SKILLGO_MAX_UNCOMPRESSED_BYTES:-262144000}
      SKILLGO_MAX_ARCHIVE_FILES: ${SKILLGO_MAX_ARCHIVE_FILES:-500}
    volumes:
      - skillgo-storage:/var/lib/skillgo/storage
    networks:
      - backend
      - model-egress
    depends_on:
      db:
        condition: service_healthy
    cap_drop: ["ALL"]
    security_opt: ["no-new-privileges:true"]
    read_only: true
    tmpfs:
      # Starlette spools uploaded files >1 MiB to /tmp before the endpoint
      # reads them: one maxed request is 5 x 200 MiB = ~1 GiB, so 2g gives
      # 2x headroom (RAM-backed, vanishes on restart).
      - /tmp:rw,nosuid,nodev,noexec,size=2g
    pids_limit: 256
    # Spool (tmpfs counts here) + in-memory file bytes + transients + baseline
    # for one maxed 5x200 MiB upload request: ~2.5g. 4g keeps headroom.
    mem_limit: 4g
    cpus: 1.0
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2)"]
      interval: 5s
      timeout: 3s
      retries: 20
    restart: unless-stopped

  worker:
    build:
      context: ./backend
    command: ["python", "-m", "app.sandbox_worker"]
    user: "10001:10001"
    group_add:
      - "${SKILLGO_DOCKER_GID:-999}"
    environment:
      SKILLGO_ENVIRONMENT: production
      SKILLGO_ENVIRONMENT_PREPARATION_ENABLED: ${SKILLGO_ENVIRONMENT_PREPARATION_ENABLED:-false}
      SKILLGO_ENVIRONMENT_BASE_IMAGE: ${SKILLGO_ENVIRONMENT_BASE_IMAGE:-}
      SKILLGO_ENVIRONMENT_QUEUE_WAIT_SECONDS: ${SKILLGO_ENVIRONMENT_QUEUE_WAIT_SECONDS:-3600}
      SKILLGO_DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-skillgo}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-skillgo}
      SKILLGO_STORAGE_ROOT: /var/lib/skillgo/storage
      SKILLGO_DURABLE_CHECKPOINTS_ENABLED: ${SKILLGO_DURABLE_CHECKPOINTS_ENABLED:-false}
      SKILLGO_JWT_SECRET: ${SKILLGO_JWT_SECRET:?set SKILLGO_JWT_SECRET}
      SKILLGO_MODEL_BASE_URL: ${SKILLGO_MODEL_BASE_URL:-}
      SKILLGO_MODEL_API_KEY: ${SKILLGO_MODEL_API_KEY:-}
      SKILLGO_MODEL_NAME: ${SKILLGO_MODEL_NAME:-}
      SKILLGO_MODEL_TIMEOUT_SECONDS: ${SKILLGO_MODEL_TIMEOUT_SECONDS:-0}
      SKILLGO_MODEL_CONNECT_TIMEOUT_SECONDS: ${SKILLGO_MODEL_CONNECT_TIMEOUT_SECONDS:-15}
      SKILLGO_MODEL_FIRST_CHUNK_TIMEOUT_SECONDS: ${SKILLGO_MODEL_FIRST_CHUNK_TIMEOUT_SECONDS:-600}
      SKILLGO_MODEL_STREAM_STALL_TIMEOUT_SECONDS: ${SKILLGO_MODEL_STREAM_STALL_TIMEOUT_SECONDS:-600}
      SKILLGO_MODEL_TEMPERATURE: ${SKILLGO_MODEL_TEMPERATURE:-0.2}
      SKILLGO_MODEL_JSON_MODE: ${SKILLGO_MODEL_JSON_MODE:-true}
      SKILLGO_MODEL_NATIVE_TOOLS: ${SKILLGO_MODEL_NATIVE_TOOLS:-true}
      SKILLGO_MODEL_TLS_VERIFY: ${SKILLGO_MODEL_TLS_VERIFY:-true}
      SKILLGO_SANDBOX_WORKER_ENABLED: ${SKILLGO_SANDBOX_WORKER_ENABLED:-false}
      SKILLGO_SANDBOX_RUNTIME: ${SKILLGO_SANDBOX_RUNTIME:-runsc}
      SKILLGO_ARTIFACT_DELIVERY_ONLY: ${SKILLGO_ARTIFACT_DELIVERY_ONLY:-true}
      SKILLGO_CONTEXT_OBSERVABILITY: ${SKILLGO_CONTEXT_OBSERVABILITY:-false}
      SKILLGO_WORKFLOW_AUTO_DELIVERY_VERSION_IDS: ${SKILLGO_WORKFLOW_AUTO_DELIVERY_VERSION_IDS:-}
      SKILLGO_DELIVERY_ONLY_SKILL_IDS: ${SKILLGO_DELIVERY_ONLY_SKILL_IDS:-}
      SKILLGO_SANDBOX_IMAGE: ${SKILLGO_SANDBOX_IMAGE:-skillgo/sandbox-runtime:local}
      SKILLGO_SANDBOX_POLL_SECONDS: ${SKILLGO_SANDBOX_POLL_SECONDS:-1}
      SKILLGO_SANDBOX_WORKER_LEASE_SECONDS: ${SKILLGO_SANDBOX_WORKER_LEASE_SECONDS:-90}
      SKILLGO_SANDBOX_WORKER_HEARTBEAT_SECONDS: ${SKILLGO_SANDBOX_WORKER_HEARTBEAT_SECONDS:-15}
      SKILLGO_SANDBOX_WORKER_MAX_ATTEMPTS: ${SKILLGO_SANDBOX_WORKER_MAX_ATTEMPTS:-3}
      SKILLGO_SANDBOX_JOB_TIMEOUT_SECONDS: ${SKILLGO_SANDBOX_JOB_TIMEOUT_SECONDS:-0}
      SKILLGO_SANDBOX_COMMAND_TIMEOUT_SECONDS: ${SKILLGO_SANDBOX_COMMAND_TIMEOUT_SECONDS:-120}
      SKILLGO_SANDBOX_MAX_AGENT_TURNS: ${SKILLGO_SANDBOX_MAX_AGENT_TURNS:-300}
      SKILLGO_SANDBOX_MAX_AGENT_TOOL_CALLS: ${SKILLGO_SANDBOX_MAX_AGENT_TOOL_CALLS:-480}
      SKILLGO_SANDBOX_MEMORY: ${SKILLGO_SANDBOX_MEMORY:-2g}
      SKILLGO_SANDBOX_NANO_CPUS: ${SKILLGO_SANDBOX_NANO_CPUS:-1000000000}
      SKILLGO_SANDBOX_PIDS_LIMIT: ${SKILLGO_SANDBOX_PIDS_LIMIT:-128}
      SKILLGO_SANDBOX_MAX_ARTIFACT_BYTES: ${SKILLGO_SANDBOX_MAX_ARTIFACT_BYTES:-52428800}
    volumes:
      - skillgo-storage:/var/lib/skillgo/storage
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - backend
      - model-egress
    depends_on:
      db:
        condition: service_healthy
    cap_drop: ["ALL"]
    security_opt: ["no-new-privileges:true"]
    read_only: true
    tmpfs:
      - /tmp:rw,nosuid,nodev,noexec,size=64m
    pids_limit: 128
    # Workers stream sandbox exec I/O and build durable checkpoint archives;
    # 512m OOM-killed long-lived workers mid-tool (PPT/image jobs, RSS growth).
    mem_limit: 2g
    cpus: 0.5
    restart: unless-stopped
    deploy:
      replicas: 12
    profiles: ["sandbox"]

  environment-worker:
    build:
      context: ./backend
    command: ["python", "-m", "app.environment_worker"]
    user: "10001:10001"
    group_add: ["${SKILLGO_DOCKER_GID:-999}"]
    environment:
      SKILLGO_ENVIRONMENT: production
      SKILLGO_DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-skillgo}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-skillgo}
      SKILLGO_ENVIRONMENT_PREPARATION_ENABLED: ${SKILLGO_ENVIRONMENT_PREPARATION_ENABLED:-false}
      SKILLGO_ENVIRONMENT_BASE_IMAGE: ${SKILLGO_ENVIRONMENT_BASE_IMAGE:-}
      SKILLGO_ENVIRONMENT_BUILD_SECONDS: ${SKILLGO_ENVIRONMENT_BUILD_SECONDS:-900}
      SKILLGO_SANDBOX_RUNTIME: ${SKILLGO_SANDBOX_RUNTIME:-runsc}
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks: [backend]
    depends_on:
      db:
        condition: service_healthy
    cap_drop: ["ALL"]
    security_opt: ["no-new-privileges:true"]
    read_only: true
    tmpfs: ["/tmp:rw,nosuid,nodev,noexec,size=64m"]
    # Wheel resolution/build spiked above 512m when preparing environments.
    mem_limit: 1g
    cpus: 0.5
    pids_limit: 128
    restart: unless-stopped
    profiles: ["environments"]

  sandbox-runtime:
    image: ${SKILLGO_SANDBOX_IMAGE:-skillgo/sandbox-runtime:local}
    build:
      context: ./sandbox-runtime
    profiles: ["build-only"]

  web:
    build:
      context: ./frontend
    ports:
      - "${SKILLGO_WEB_BIND:-127.0.0.1}:${SKILLGO_WEB_PORT:-8080}:8080"
    networks:
      - public
      - backend
    depends_on:
      api:
        condition: service_healthy
    cap_drop: ["ALL"]
    security_opt: ["no-new-privileges:true"]
    read_only: true
    tmpfs:
      # nginx scratch space (read_only rootfs). API bodies are streamed through
      # (proxy_request_buffering/proxy_buffering off in nginx.conf), so this no
      # longer needs to hold spooled upload bodies.
      - /var/cache/nginx:rw,nosuid,nodev,noexec,size=96m,uid=101,gid=101,mode=0750
      - /var/run:rw,nosuid,nodev,noexec,size=4m,uid=101,gid=101,mode=0750
    pids_limit: 128
    mem_limit: 256m
    cpus: 0.5
    restart: unless-stopped

networks:
  public:
  backend:
    internal: true
  model-egress:
    # Control-plane egress for the configured private model. Skill runtime
    # sandboxes must not inherit this network.

volumes:
  skillgo-postgres:
  skillgo-storage: