wsl-labs GitHub

⚙️ Especificaciones Técnicas — WSL Container Center#

Versión: v1 Estado: 🟢 Activo Audiencia: 👥 Técnico, DevOps, reclutadores Objetivo: Stacks, puertos, endpoints del panel, esquema del catálogo, multi-contenedor + red y health IPv4/IPv6

🗺️ Esquema#

flowchart LR
    Panel["🧭 Panel :9092"]
    subgraph API["Endpoints /api/wslc"]
        OV["/overview"]
        BU["/build"]
        UP["/up"]
        DN["/down"]
        LG["/logs"]
    end
    Panel --> API
    API -->|"spawn wslc.exe"| Engine["🐳 Motor wslc"]
    Engine --> S1["starter: node :8101 · python :8102<br/>go :8103 · nginx :8104"]
    Engine --> S2["platform: redis :8105 · postgres :8106<br/>lamp :8107 · mongo :8112 (con red)"]
    Engine --> S3["infra: rabbitmq :8109 · prom+grafana :8110/:8111<br/>elasticsearch :8113 · jenkins :8114"]

🖥️ Base de ejecución#

ComponenteEstado actual
Motor de contenedoreswslc (WSL 2.9+, preview) en C:\Program Files\WSL\wslc.exe
Panel principaldashboard-server/server.js en 9092 (solo 127.0.0.1)
Puente Windows → motorEl panel ejecuta wslc.exe como proceso hijo
Launcher Windowswsl-labs-launcher.exe compilado con Go 1.21 (stdlib puro, cero dependencias)
Instalador WindowsInno Setup .exe distribuido por GitHub Releases
Fuente de verdadcontainers/containers.config.json (casos, imágenes, puertos, redes, health)

🧬 Stacks por caso#

CasoTítuloCategoríaImágenesRed
01API Node.jsstarterwsl-labs/node-api (custom, node:20-alpine)
03API Python (Flask)starterwsl-labs/python-api (custom, python:3.12-alpine)
10API Gostarterwsl-labs/go-api (custom, multi-stage)
06Nginx webstarterwsl-labs/nginx-web (custom, nginx:alpine)
04Cache Redis + appplatformwsl-labs/redis-app + redis:7-alpinewslc-redis-net
05API + PostgreSQLplatformwsl-labs/pg-app + postgres:15wslc-pg-net
02LAMP (PHP + MariaDB)platformwsl-labs/php-lamp + mariadb:10.6wslc-lamp-net
09App multi-servicioplatformwsl-labs/multi-backend + mongo:7wslc-multi-net
07RabbitMQinfrarabbitmq:3-management (público)
08Prometheus + Grafanainfraprom/prometheus + grafana/grafana (públicas)wslc-obs-net
11Elasticsearchinfraelasticsearch:8.11.0 (público)
12Jenkins CIinfrajenkins/jenkins:lts (público)
Las imágenes custom se construyen con wslc build -t <imagen> <contexto> desde un Dockerfile en containers/NN-*/. Las imágenes públicas se descargan al ejecutar wslc run y no requieren 📦 Construir.

🔌 Puertos — casos en localhost#

CasoPuerto hostURL
🧭 Panel9092http://localhost:9092
01 API Node.js8101http://localhost:8101
03 API Python8102http://localhost:8102
10 API Go8103http://localhost:8103
06 Nginx web8104http://localhost:8104
04 Redis + app8105http://localhost:8105
05 API + PostgreSQL8106http://localhost:8106
02 LAMP8107http://localhost:8107
07 RabbitMQ8109http://localhost:8109
08 Prometheus / Grafana8110 / 8111http://localhost:8110 · http://localhost:8111
09 Multi-servicio (Mongo)8112http://localhost:8112
11 Elasticsearch8113http://localhost:8113
12 Jenkins CI8114http://localhost:8114
RabbitMQ además expone 5672 (protocolo AMQP) junto a 8109 (panel de administración).

📡 Endpoints del panel#

Todos bajo http://localhost:9092. Los /api/* respetan el token opcional (ver más abajo); las acciones POST están además limitadas por rate-limit.

MétodoRutaDescripción
GET/api/wslc/overviewDisponibilidad del motor + estado de los 12 casos (built, running, totales)
POST/api/wslc/buildwslc build -t <imagen> <contexto> por cada imagen del caso { id }
POST/api/wslc/upCrea la red (si aplica) y wslc run -d de cada contenedor del caso
POST/api/wslc/downwslc stop + wslc rm de cada contenedor (+ network rm)
POST/api/wslc/logswslc logs del contenedor principal del caso
GET/, /index.html, /dashboard.css, /dashboard.jsUI estática

Contrato de las acciones POST — cuerpo { "id": "01" }. Respuesta:

{ "ok": true, "id": "01", "action": "up", "output": "[run wslc-node-api] OK\n..." }
AspectoValor
id válidoRegex ^[\w-]+$ y debe existir en el catálogo (si no → 400/404)
Body máximo8 KB (excede → error)
Timeout build/up600 s (pull + capas + arranque)
Timeout logs12 s
Timeout health3 s
Rate-limit30 POST / IP / 60 s

📇 Esquema del catálogo (containers/containers.config.json)#

Cabecera del documento:

CampoEjemploRol
project"WSL Container Center"Nombre mostrado en el panel
subtitle"Levanta y controla contenedores con wslc…"Subtítulo del panel
engine"wslc"Motor de contenedores
portBase8100Base de puertos del catálogo
cases[]arrayDefinición de cada caso

Campos de cada caso:

CampoAplica aDescripción
idtodosIdentificador ("01") usado por la API
name / titletodosNombre corto y título mostrado en la tarjeta
descriptiontodosTexto descriptivo del caso
categorytodosstarter, platform o infra
port / urltodosPuerto y URL publicados en localhost
healthProtocoltodoshttp (todos los casos actuales)
networkmulti-contenedorNombre de la red wslc a crear (p. ej. wslc-pg-net)
build[]casos customLista de { image, context } a construir con wslc build
containers[]todosLista de { name, image, ports[], env[], volumes[] } a ejecutar con wslc run
requirementstodosDatos medidos: { imageSizeMB, ramIdleMB, ramMinMB, ramRecMB }
limitstodosTope de recursos aplicado al run: { memMB, cpus } (-m, --cpus)
containers[].volumes[]casos con datos"nombre:/ruta" — volumen con nombre que persiste al bajar/levantar

Ejemplo de un caso multi-contenedor (05):

{
  "id": "05",
  "network": "wslc-pg-net",
  "build": [{ "image": "wsl-labs/pg-app:latest", "context": "containers/05-postgres-api" }],
  "containers": [
    { "name": "wslc-postgres", "image": "postgres:15", "ports": [], "env": ["POSTGRES_PASSWORD=wsl-labs", "POSTGRES_DB=app"] },
    { "name": "wslc-pg-app", "image": "wsl-labs/pg-app:latest", "ports": ["8106:8000"], "env": ["PG_HOST=wslc-postgres"] }
  ]
}
El contenedor principal de un caso es el que publica el puerto del caso (ports empieza por <port>:). El panel usa ese contenedor para el health-check y para 📄 Logs.

🕸️ Multi-contenedor + red#

Los casos platform y 08 observabilidad levantan más de un contenedor sobre una red wslc dedicada:

  1. ▶ Levantar primero ejecuta wslc network create <network> (idempotente).
  2. Cada contenedor se lanza con --network <network>, de modo que se **resuelven por

nombre** (p. ej. la app apunta a su base con PG_HOST=wslc-postgres, REDIS_HOST=wslc-redis, DB_HOST=wslc-mariadb, MONGO_HOST=wslc-mongo).

  1. ⏹ Bajar elimina los contenedores y luego la red con wslc network rm.

🩺 Health-check IPv4 + IPv6#

AspectoImplementación
Hosts probados127.0.0.1 y ::1 (evita falsos "abajo" por bind IPv6)
Protocolohttp: GET /, sano si el status es < 500
Detección de "construido"Se compara el nombre de imagen del caso contra wslc images
Detección de "corriendo"Se busca el contenedor principal en wslc list
Estadosrunning · degraded · stopped · missing · unavailable

🔒 Seguridad y robustez del panel#

AspectoImplementación
BindSolo 127.0.0.1 — no expuesto a la red
AutenticaciónToken Bearer/Cookie opcional vía WSL_LABS_TOKEN (sin él, modo dev abierto)
Validación de inputsid validado con regex ^[\w-]+$ contra el catálogo antes de ejecutar
Body limit8 KB máximo en requests POST
Rate limiting30 requests POST / IP / 60 s (en memoria, sin dependencias)
Timeoutsbuild/up 600 s · logs 12 s · health 3 s
Error handlingErrores internos capturados; respuesta sin volcar internals

Variables de entorno#

VariableEfecto
PORTPuerto del panel (default 9092)
WSL_LABS_WSLCRuta a wslc.exe (override del default C:\Program Files\WSL\wslc.exe)
WSL_LABS_TOKENActiva autenticación por token
WSL_LABS_ROOT_WINRaíz del repo en Windows (default: carpeta padre del servidor)

🧪 CI/CD — GitHub Actions#

WorkflowTriggerDescripción
docspush / PRmarkdownlint sobre la documentación
dashboardpush / PRTests Node del panel
build-windowstag v*.*.*Compila el launcher Go y el instalador Inno Setup

📚 Documentos relacionados#

Fuente: docs/TECHNICAL_SPECS.md