Skip to main content

debug-deploy

This skill should be used when a Dokploy deployment fails, gets stuck, or behaves incorrectly after deploying — provides an end-to-end decision tree that locates the failed run, reads the right logs, inspects the container and Traefik state, summarises root cause with AI, and recovers safely. Triggers: "my dokploy deploy failed", "deployment stuck", "build error in dokploy", "app crashed after deploy", "diagnose failed deployment", "dokploy deploy not working", "why did my deploy fail", "recover from broken deploy".

Source facts

Repository
Agents-Store/cursor-plugins
Last source activity
October 3, 2026 at 23:16
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
debug-deploy
description
This skill should be used when a Dokploy deployment fails, gets stuck, or behaves incorrectly after deploying — provides an end-to-end decision tree that locates the failed run, reads the right logs, inspects the container and Traefik state, summarises root cause with AI, and recovers safely. Triggers: "my dokploy deploy failed", "deployment stuck", "build error in dokploy", "app crashed after deploy", "diagnose failed deployment", "dokploy deploy not working", "why did my deploy fail", "recover from broken deploy".
# Debug a Failed Dokploy Deployment This is the **canonical workflow** when a Dokploy deployment fails, gets stuck, or the production site does not change after a "successful" deploy. Work through the steps in order — each step narrows the cause and feeds the next. Companion command: **`/dokploy-dev:debug [applicationId|composeId]`** runs this entire chain. > **Reading logs (Dokploy v0.29.0+; current v0.30.7, stable latest v0.30.8):** Runtime **and** build logs are available directly over the REST API / MCP — no SSH or Beszel needed (the old [issue #3719](https://github.com/Dokploy/dokploy/issues/3719) gap is closed). There are two distinct artifacts: the **build log** (`deployment-readLogs { deploymentId, tail }`) explains why an image failed to build; the **runtime log** (`application-readLogs` / per-container `compose-readLogs` / `{db}-readLogs`, all with `tail`/`since`/`search`) explains why a running container is crashing. For a multi-container Compose stack you must enumerate the containers and read **each** one — see the [`read-logs`](../read-logs/SKILL.md) skill, which this workflow uses for every log read below. --- ## Step 0 — Confirm the platform itself is healthy Before blaming the deploy, rule out the server. 1. `mcp__plugin_dokploy-dev_dokploy__settings-health` — must return ok. 2. `mcp__plugin_dokploy-dev_dokploy__settings-checkInfrastructureHealth` — core services: returns `{ postgres: { status }, traefik: { status } }` (no Redis since v0.30.0). 3. `mcp__plugin_dokploy-dev_dokploy__settings-getDockerDiskUsage` — if the disk is >90% full, builds silently fail with "no space left on device". Run `/dokploy-dev:cleanup` to recover. (v0.30+: `dockerDiskUsage-getDiskUsage { serverId }` does the same for a remote server.) 4. `mcp__plugin_dokploy-dev_dokploy__settings-getDokployVersion` — note the version; some bugs are version-specific. 5. **v0.30+ host diagnostics (read-only):** `mcp__plugin_dokploy-dev_dokploy__docker-getServerHealth { serverId?, sinceHours? }` — disk, memory/CPU, inotify limits, Docker network IP-pool usage, recent daemon errors, memory/CPU reservations; and `docker-getEvents { serverId?, minutes? }` — what the daemon did recently (OOM kills, restarts, image pulls, network connects). These checks target the usual causes of a deploy that stalls without a clear error: a full disk, exhausted inotify watches, an exhausted Docker network address pool, or memory/CPU reservations the host cannot satisfy. If any of these fail, fix the server first. Do not proceed. --- ## Step 1 — Locate the failed deployment Find the most recent deployment for the resource and confirm its status. **For a single resource (you know the ID):** ``` mcp__plugin_dokploy-dev_dokploy__deployment-all → { applicationId: "<id>" } # applications ONLY mcp__plugin_dokploy-dev_dokploy__deployment-allByCompose → { composeId: "<id>" } # compose stacks mcp__plugin_dokploy-dev_dokploy__deployment-allByServer → { serverId: "<id>" } # server-level deploys ``` (`deployment-all` takes only `applicationId` — compose and server deploys have their own list tools.) **For "I don't know which app failed":** ``` mcp__plugin_dokploy-dev_dokploy__deployment-allCentralized # all deployments across the instance mcp__plugin_dokploy-dev_dokploy__deployment-queueList # what's currently queued / in-flight ``` In both responses, look at `status`. Values you care about: | Status | Meaning | Next step | |---|---|---| | `running` | Build / deploy in progress | Step 2 (read live logs) | | `error` | Deploy failed | Step 2, then Step 3 | | `done` but site unchanged | Compose-mode mismatch — you deployed the standalone app while production runs from compose, or vice-versa | Re-check via `project-one`; deploy the *compose* resource using `compose-deploy` | | `queued` for >2 minutes | Queue stuck | Step 5 (recovery: `cleanQueues`). If queued deploys pile up on a busy server: builds run in per-server queues since v0.29.9 — tune concurrency via `settings-updateBuildsConcurrency { buildsConcurrency }` (Dokploy host) / `server-updateBuildsConcurrency { serverId, buildsConcurrency }` (remote servers); 1–100 per server, default 1 (the OSS max-2 clamp existed only in v0.29.9–v0.29.10; removed in v0.29.11) | Save the `deploymentId` of the failed run — multiple steps below take it. --- ## Step 2 — Read the logs (build vs runtime) Logs are the single most informative artifact. Pick the **right** log for the failure — the [`read-logs`](../read-logs/SKILL.md) skill has the full detail; the essentials: - **Build failed** (`status: error`, image never started) → read the **build log** for that deployment: ``` mcp__plugin_dokploy-dev_dokploy__deployment-readLogs { deploymentId: "<from Step 1>", tail: 500 } ``` **If `deployment-readLogs` isn't a registered tool in your session** (some MCP builds expose a reduced tool set — `ToolSearch` won't find it), read the identical artifact over REST instead of giving up on the log: ```bash curl -s -G "$DOKPLOY_URL/api/deployment.readLogs" -H "x-api-key: $DOKPLOY_API_KEY" \ --data-urlencode "deploymentId=<from Step 1>" --data-urlencode "tail=500" | tr '\r' '\n' ``` CLI alternative: `dokploy deployment read-logs --deploymentId <id> --tail 500`. Always read the actual build log before forming a root cause — a ~15s "instant" failure looks the same for a dozen different causes (corepack, lockfile, frozen-install policy, OOM), and only the log distinguishes them. See the [`read-logs`](../read-logs/SKILL.md) §3 fallback for details. - **Build succeeded but the container is crashing / erroring at runtime** → read the **runtime log**: - App: `mcp__plugin_dokploy-dev_dokploy__application-readLogs { applicationId, tail: 300, since: "1h", search?: "error" }` - **Compose stack: read every container.** First enumerate (`compose-one { composeId }` → `appName`/`composeType`; then `docker-getContainersByAppNameMatch { appName, appType: "docker-compose" }` for compose, or `docker-getStackContainersByAppName { appName }` for swarm). Then loop `compose-readLogs { composeId, containerId, tail, since, search }` for **each** container — or just run `/dokploy-dev:compose-logs <compose>`. - Database: `{type}-readLogs { {type}Id, tail, since, search }`. `tail` is 1–10000 (default 100); `since` is `all` or `<n>{s|m|h|d}`; `search` is a server-side substring filter. The runtime-log `.data` is a newline-joined, timestamp-prefixed string. **Scan the log for these patterns first** — they account for the majority of Dokploy build failures: | Pattern in log | Root cause | Fix | |---|---|---| | `no space left on device` | Disk full | Step 5 → `/dokploy-dev:cleanup` | | `failed to compute cache key` / `failed to fetch` | Stale build cache or bad layer | `application-killBuild`, then `application-redeploy` | | `error: failed to solve` | Dockerfile error / missing context | Inspect Dockerfile / context path; fix and `application-saveBuildType` | | `Authentication failed` (git) | Wrong / expired token | `github-update` / `gitlab-update` / `bitbucket-update` / `gitea-update` | | `nixpacks` cannot detect language | Wrong build type | Switch to `dockerfile` via `application-saveBuildType` | | `MODULE_NOT_FOUND` / `ImportError` | Missing dep or wrong working dir | Check `dockerContextPath` and Dockerfile `WORKDIR` | | Build times out | Heavy image or slow network | Increase timeout, use multi-stage builds, or pre-build & push image | | App exits 0/1 immediately after start | Missing runtime env var | Step 3 (check env — names only, values are redacted by default), then `saveEnvironment` + `redeploy` | --- ## Step 3 — Inspect the container state If the *build* succeeded but the *runtime* is broken, switch from build logs to container introspection. ``` mcp__plugin_dokploy-dev_dokploy__docker-getContainersByAppLabel → { appName: "<appName>", type: "standalone" } # type is REQUIRED: "standalone" | "swarm" ``` Returns the list of running containers tagged with this app's Docker label (each `{ containerId, name, state, status }`). You want to see: - **State** — `running`, `exited`, `restarting` (crash loop) - **Health** — `healthy`, `unhealthy`, `starting`, `none` - **Image** — confirm Dokploy is running the image it just built (not an old one) - **Ports** — what's actually published Drill down with these as needed: | Tool | When to use | |---|---| | `mcp__plugin_dokploy-dev_dokploy__docker-getConfig` | Inspect full container config: command, mounts, network, restart policy. Catches misconfigured `command:` overrides and missing mounts. **`Env` comes back as `[REDACTED]`** unless `DOKPLOY_REDACT_ENV=false` — see "Env and credentials" below | | `mcp__plugin_dokploy-dev_dokploy__docker-getServiceContainersByAppName` | For Swarm-deployed apps — finds containers across nodes | | `mcp__plugin_dokploy-dev_dokploy__docker-getStackContainersByAppName` | For compose-deployed apps — lists every service container in the stack | | `mcp__plugin_dokploy-dev_dokploy__docker-getContainersByAppNameMatch` | Loose match by app-name substring — useful when `appName` is not exact | | `mcp__plugin_dokploy-dev_dokploy__docker-killContainer` | Force-stop a wedged container | | `mcp__plugin_dokploy-dev_dokploy__docker-restartContainer` | Restart in place (no rebuild) — first try after a transient runtime failure | | `mcp__plugin_dokploy-dev_dokploy__docker-stopContainer` / `startContainer` | Graceful stop/start | | `mcp__plugin_dokploy-dev_dokploy__docker-removeContainer` | Hard-delete; Dokploy will recreate on next `deploy` | | `mcp__plugin_dokploy-dev_dokploy__docker-uploadFileToContainer` | Push a one-off config or credential without rebuilding (use sparingly — does not survive redeploy). Empty MCP schema: send it with REST `curl -F` (see `mcp-patterns`, "Multipart operations") | > **Crash loop pattern:** state oscillates between `restarting` and `exited`. Always read `docker-getConfig` and check the `RestartPolicy` and the container's exit code before chasing the wrong issue. ### Env and credentials (redaction) Since `@dokploy/mcp` 0.30.0 the MCP responses of `application-one`, `compose-one`, `{db}-one` and `docker-getConfig` show `env`, `Env`, `buildArgs`, passwords and tokens as `[REDACTED]` — not even the variable names. Do not conclude "the variable is empty/missing" from that. Diagnose in this order: 1. **The log names the culprit.** `getaddrinfo ENOTFOUND db`, `ECONNREFUSED postgres:5432`, `Missing required env DATABASE_URL`, a stack trace through a config loader — Step 2 usually already shows the host or variable name without any value. 2. **List variable names without values** (REST is not redacted, so keep the values out of your output): `curl -s -G "$DOKPLOY_URL/api/application.one" -H "x-api-key: $DOKPLOY_API_KEY" --data-urlencode "applicationId=<id>" | jq -r '(.env // "") | split("\n")[] | select(test("^[A-Za-z_][A-Za-z0-9_]*=")) | split("=")[0]'`. 3. **Need the values?** Ask the user, or set `DOKPLOY_REDACT_ENV=false` in the MCP `env` block and reconnect — a conscious choice, because everything returned then enters the model context. Never write `[REDACTED]` back through `application-saveEnvironment`: it replaces the whole `env` string. The "change one variable, keep the rest" recipe is in the `mcp-patterns` skill ("Redaction"). --- ## Step 4 — Check the request path (502 / 504 / wrong content) If the container is running but HTTPS clients see 502 / 504 / wrong response, the failure is between Traefik and the container. ``` mcp__plugin_dokploy-dev_dokploy__application-readTraefikConfig → { applicationId } ``` Look for: | Symptom in Traefik config | Cause | Fix | |---|---|---| | Service URL points to wrong port | Domain port doesn't match the port the app actually listens on | `domain-update` to correct port | | `Bad Gateway` from Traefik logs | App bound to `127.0.0.1` instead of `0.0.0.0` | Fix env / startup args in the app code; redeploy | | No router for this host | Domain not attached, or attached to wrong resource (app vs compose) | `domain-byApplicationId` / `domain-byComposeId`; re-create with `domain-create` | | TLS cert error | Domain added before DNS propagation, or DNS not pointing at server | `domain-validateDomain`; fix DNS; delete and re-add with `https: true, certificateType: "letsencrypt"` | | App not on `dokploy-network` | Container isn't routable from Traefik | Inspect via `docker-getConfig`; for compose, every public-facing service needs `networks: [dokploy-network]`. v0.30+: check the service's `networkIds` / `detachDokployNetwork` (compose: `serviceNetworks`) — a detached `dokploy-network` makes a service unreachable from Traefik; `network-inspect` shows who is attached | If the resource is exposing ports directly (`ports: ["80:80"]` in compose), there will be a **port collision** with Traefik (80/443/8080). Either remove the explicit port mapping (let Traefik handle it via labels) or change the host port. --- ## Step 5 — Recover Pick the smallest action that unblocks the user. Always confirm destructive operations first. | Goal | Tool | Notes | |---|---|---| | Stop the failing build immediately | `application-killBuild` / `compose-killBuild` | Aborts the in-progress builder process | | Cancel a queued/in-flight deploy | `application-cancelDeployment` / `compose-cancelDeployment` | Marks the deploy as cancelled, releases the queue slot | | Clear a stuck queue | `application-cleanQueues` / `compose-cleanQueues` / `settings-cleanAllDeploymentQueue` | Use when multiple deploys are wedged | | Forget a specific bad deployment record | `deployment-removeDeployment` | Removes one row from history without affecting others (NOT `application-dropDeployment` — that uploads a zip and deploys it) | | Wipe deployment history | `application-clearDeployments` / `compose-clearDeployments` | Use sparingly — destroys audit trail | | Force "running" state on a healthy-but-misreported container | `application-markRunning` | Cosmetic only — does not start anything | | Roll back to the previous good version | `mcp__plugin_dokploy-dev_dokploy__rollback-rollback { rollbackId }` | Look up valid rollbacks via the app's `rollbacks` array on `application-one`. Use `/dokploy-dev:rollback` for the guided flow | | Reclaim disk and clear build cache | `settings-cleanDockerBuilder`, `cleanUnusedImages`, `cleanUnusedVolumes`, `cleanStoppedContainers` | Use `/dokploy-dev:cleanup` for the guided flow | | Kill a wedged runtime container | `docker-killContainer` then `application-redeploy` | Fastest path out of a crash loop | --- ## Step 6 — Ask the AI to summarise (when available) If an AI provider is configured (`mcp__plugin_dokploy-dev_dokploy__ai-getEnabledProviders` returns at least one), let it digest the log and recommend a fix instead of grepping manually. `ai-analyzeLogs` takes the **log text you already fetched in Step 2** — not a `deploymentId`: ``` mcp__plugin_dokploy-dev_dokploy__ai-analyzeLogs → {
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub