Skip to content

Latest commit

 

History

History
83 lines (61 loc) · 3.24 KB

File metadata and controls

83 lines (61 loc) · 3.24 KB

PITFALLS.md — dsh in Docker, the ops edition

The incidents behind dsh-guard. Read before touching a profile, a plugin, or a restart in a container.

1. One bad dsh.profile.bundles entry bricks every boot

dsh web resolves every bundle name to a real installed package with a dsh.bundle.patch and fails loud on the first bad entry — no skip-fallback. Symptom:

dsh: cannot resolve profile bundle "@linxin666/dsh-web-ui-all" from the dsh
installation or /root/.dsh/profiles/web; run 'dsh plugin --profile web install'

Cause seen in the wild: a market install wrote a bundle name whose npm package has no usable bundle. Until package.json is fixed, every restart crash-loops the container.

Rule: after any plugin add/remove, run sh ~/.dsh/dsh-guard/bundle-validate.sh --profile web BEFORE restarting. --fix removes bad entries; reset-profile.sh restores a known-good profile (base + web-app + dsh-pet) with a backup. Never hand-delete package.json when the guard can do it safely.

2. The proxy (PID 1) does not respawn dsh web

/app/entrypoint.sh starts dsh web --port 3079 in the background, then exec node index.js (the proxy on :3080 → 127.0.0.1:3079). Kill dsh web and it stays dead — you must relaunch it. The proxy itself may throw ECONNREFUSED on proxied requests while the backend is down, which restarts the whole container (--restart unless-stopped).

Rule: restart with dsh-guard/restart-web.sh (detached, delayed, waits for readiness), never by just killing the process from an agent's own tool call — that can kill the very turn running it.

3. This image has no ps/pgrep/curl

Use /proc/*/cmdline scans or Node (fetch/net) instead. The guard scripts already do.

4. Docker-on-Windows (WSL2 host): "open produced file" dies

The kernel reports "microsoft", so DSH's native opener picks the WSL path and spawns wslpathspawn wslpath ENOENT (and powershell.exe would be next). Fix is a patch-layer override, not a shim:

# ~/.dsh/profiles/web/cordis.patch.yml
- id: api-gateway
  config:
    nativeOpen: false

The UI then shows produced paths as copyable text instead of a dead button.

5. Host bundles: named exports only

export default makes DSH's loader unwrap to the bare function and silently drop inject/namecannot get property "webServer" without inject at boot. Use export function apply + export const inject + export const name. Clients must never declare an inject they don't require (pending (waiting for service: …) forever). Full plugin-authoring lessons: see the dsh-video-player repo's PITFALLS.md.

6. link: installs can't see the profile's node_modules

dsh plugin add <local-dir> symlinks the package; Node resolves its imports from the realpath, outside the profile's node_modules. Bridge @deepseek-ai/dsh-settings (from ~/.dsh/profiles/node_modules/@deepseek-ai) and schemastery (from ~/.dsh/profiles/web/node_modules) into the plugin's own node_modules/.

7. Test risky boots on another port first

dsh web --port 3099 --no-open    # same profile, captured logs, no risk to :3079

(dsh web does not accept --profile; the subcommand already implies web.)