Files
tiny-forge/docs/docker-diagnostic-hints.md
alexei.dolgolyov 670948f113 fix: address code review findings for DNS management
- CRITICAL: Change DNS zones endpoint from GET to POST to avoid
  leaking API token in URL query parameters
- HIGH: Add sync.RWMutex to protect dnsProvider field in Server,
  Deployer, and proxy Manager against concurrent read/write races
- HIGH: Capture old DNS provider reference synchronously before
  launching background cleanup goroutine
- HIGH: Use getDNS()/getDNSProviderLocked() accessors instead of
  direct field reads in all DNS operations
2026-04-02 14:54:15 +03:00

5.4 KiB

Feature: Docker Diagnostic Hints on Disconnection

Problem: When Docker is unreachable, the UI shows a generic "Docker disconnected" label with no actionable guidance. Users (especially on Windows/macOS where Docker Desktop must be running) have no idea what's wrong or how to fix it.

Goal: Enrich the health-check response with a structured diagnostic object so the frontend can display platform-aware, actionable hints.


Backend Changes

1. Enhance GET /api/health response (health.go)

Currently returns { "docker": true|false }. Change to:

{
  "docker": {
    "connected": false,
    "error": "dial unix /var/run/docker.sock: connect: no such file or directory",
    "category": "socket_not_found",
    "hints": [
      "Docker Desktop does not appear to be running.",
      "Start Docker Desktop and wait for it to finish initializing.",
      "If using a custom socket path, check DOCKER_HOST env variable."
    ],
    "platform": "windows",
    "checked_at": "2026-03-30T12:34:56Z"
  }
}

2. Create a Docker diagnostics module (new file, e.g. internal/docker/diagnostics.go)

Classify the Ping error into a diagnostic category and generate platform-specific hints. Follow the pattern already established in hints.go for proxy validation.

Error categories to handle:

Category Error signature Windows hints Linux hints macOS hints
socket_not_found no such file or directory, The system cannot find the file specified Docker Desktop not running; start it from Start Menu or system tray Docker daemon not running; sudo systemctl start docker Docker Desktop not running; start from Applications or open -a Docker
connection_refused connection refused Docker Desktop is starting up — wait ~30s and retry Docker daemon is starting; sudo systemctl status docker Docker Desktop is starting; check the whale icon in the menu bar
permission_denied permission denied Run the application as Administrator, or add your user to the docker-users group Add your user to the docker group: sudo usermod -aG docker $USER then re-login Check Docker Desktop settings -> Resources -> File Sharing
timeout context deadline exceeded, i/o timeout Docker Desktop may be overloaded or hanging — restart it Docker daemon may be overloaded; check journalctl -u docker Docker Desktop may be unresponsive; restart from menu bar
tls_error tls:, certificate Check Docker TLS cert configuration and DOCKER_TLS_VERIFY Verify certs in ~/.docker/ match daemon config Check ~/.docker/ TLS configuration
unknown (fallback) Show raw error with link to Docker Desktop troubleshooting docs Show raw error with dockerd docs link Show raw error with Docker Desktop docs link

Detect the platform via runtime.GOOS in the diagnostics module (the binary runs on the host, so this is accurate).

3. Expose runtime.GOOS once in diagnostics, don't scatter it through handlers.

4. Preserve backward compat — if any external consumer depends on the old "docker": bool shape, consider a migration path or version the health endpoint. Internal-only API can break freely.


Frontend Changes

5. Update the API type (api.ts)

interface DockerHealth {
  connected: boolean;
  error?: string;
  category?: string;
  hints?: string[];
  platform?: string;
  checked_at?: string;
}

export function getHealth(): Promise<{ docker: DockerHealth }> {
  return get<{ docker: DockerHealth }>('/api/health');
}

6. Enhance the health indicator (+layout.svelte)

When dockerConnected === false:

  • Show a clickable/expandable area (tooltip, popover, or collapsible panel) below the red dot.
  • Display the hints array as a bulleted list.
  • Optionally show the raw error in a <details> collapse for advanced users.
  • Show checked_at as relative time ("last checked 15s ago").
  • Add a manual "Retry now" button that triggers an immediate health check instead of waiting for the 30s poll.

7. Add i18n keys (en.json, ru.json)

Add keys for each hint category so hints can be translated. The backend should return category + platform identifiers; the frontend can use them to look up localized hint text instead of displaying raw English strings from the backend. This keeps i18n centralized in the frontend.


Architecture Notes

  • The proxy validator (validator.go, hints.go) already implements a similar pattern: classifying errors by substring match and returning human-readable hints. Reuse that approach for consistency.
  • Keep diagnostics pure — a function that takes an error and runtime.GOOS and returns (category string, hints []string). No side effects, easy to unit-test.
  • Consider caching the diagnostic result for a few seconds to avoid spamming Docker if the frontend retries rapidly.

Testing

  • Unit-test the diagnostics function with synthetic errors for each category x platform combination.
  • Integration-test the health endpoint with a mock Docker client that returns each error type.
  • Frontend: test that the hint UI renders correctly for each category and collapses/expands properly.