Spin up per-session lab containers with unique URLs (via Traefik), and serve a course lesson page that calls the API to create/stop labs.
- Docker (and Docker Compose v2)
- Node 18+
- For Windows: use WSL2 for best results.
-
Start Traefik (reverse proxy) and the shared
labsnetwork:docker compose -f traefik.compose.yml up -d
- Traefik dashboard: http://traefik.127.0.0.1.nip.io:8080
-
Configure environment:
cp .env.example .env # .env defaults should work locally -
Install deps & start API:
npm install npm start
-
Open the lesson:
-
Click Run Code:
- API builds
labs/hello-apiimage if missing, starts a container with labels for Traefik, and returns a URL like:http://run-<id>.127.0.0.1.nip.io
- API builds
-
Click Run Tests:
- The page will call
/api/pingon the live lab URL and show pass/fail in the terminal area.
- The page will call
-
Click Stop Lab to stop the container.
traefik.compose.ymlruns Traefik and creates a Docker networklabs.- The Express API starts lab containers on that same network, adding Traefik labels:
Host(\run-.<BASE_DOMAIN>`)` → routes to the container's port 3000.
- For local dev,
BASE_DOMAIN=127.0.0.1.nip.ioso subdomains resolve to127.0.0.1automatically.
POST /api/sessions→ start a lab, returns{ id, url }GET /api/sessions/:id/status→ check container statusPOST /api/sessions/:id/stop→ stop the container
- This MVP runs a fixed lab image (
labs/hello-api). You can extend the API to:- accept a
templateorcomposereference per lesson - mount user code volumes
- set TTL auto-shutdown
- record attempts in a database
- accept a
- For production, put Traefik behind HTTPS (e.g., with Let's Encrypt) and use a real wildcard domain.
- The lesson page now POSTs your editor contents to
POST /api/sessionsasfiles.index.js. - The API builds a per-session Docker image with your code and runs it behind Traefik.
- The live URL is returned (e.g.,
http://run-<id>.127.0.0.1.nip.io). - Stop Lab removes the container and cleans up the temp build dir (and image).
- Run Code now explicitly shows the live URL banner (display:flex) with the returned URL.
- Added
GET /api/sessions/:id/probeso the lesson can test the lab server-side (no CORS issues). - Lab container now sends permissive CORS headers (for direct browser checks too).