services: sandbox: build: . # Stable name for single-instance DX (docker exec desktop-sandbox). # Override for a second stack, or use scripts/run-instance.sh instead: # SANDBOX_CONTAINER_NAME=desktop-sandbox-1 docker compose -p sbx1 up -d container_name: ${SANDBOX_CONTAINER_NAME:-desktop-sandbox} ports: # Bind to host loopback only; tunnel/proxy for remote access. # Do not publish raw RFB :5900 — noVNC on 6080 is enough. # Host ports are overridable for multi-instance (internal stay 7090/6080): # SANDBOX_HOST_API_PORT=7091 SANDBOX_HOST_WS_PORT=6081 docker compose up -d - "127.0.0.1:${SANDBOX_HOST_API_PORT:-7090}:7090" # Desktop API - "127.0.0.1:${SANDBOX_HOST_WS_PORT:-6080}:6080" # websockify / noVNC environment: SANDBOX_HOST: "0.0.0.0" SANDBOX_API_HOST: "0.0.0.0" SANDBOX_PORT: "7090" SANDBOX_API_PORT: "7090" SANDBOX_DISPLAY: ":99" # Middle ground: larger than 1280x800 (tablet sites), smaller than # 1920x1080 (VNC/UI feels tiny). Browser window is separate # (~80% via sandbox-browser / SANDBOX_BROWSER_SIZE). SANDBOX_SIZE: "1600x900" SANDBOX_VNC_PORT: "5900" SANDBOX_WS_PORT: "6080" # Required when binding 0.0.0.0. Override for production: # SANDBOX_TOKEN=your-secret docker compose up SANDBOX_TOKEN: "${SANDBOX_TOKEN:-dev-sandbox-token}" # Reap zombie Chromium/xterm children (docker init = tini). init: true # Chromium + Xvfb need more than the default 64MB /dev/shm shm_size: "1gb" restart: unless-stopped # Debug only — raw VNC (passwordless inside container, localhost-only): # ports: # - "127.0.0.1:5900:5900"