Skip to main content

read-logs

This skill should be used whenever the user wants to read, tail, stream, or search Dokploy logs — application runtime logs, Docker Compose stack logs (every container), database logs, or deployment build logs — and especially to diagnose why something failed. Triggers: "read the logs", "show me the dokploy logs", "tail the logs", "compose logs", "all containers' logs", "container logs", "why is my app crashing", "why did my deploy fail — check the logs", "grep the logs for an error", "runtime logs", "build logs". Use it instead of telling the user logs aren't available over the API — since Dokploy v0.29.0 they are.

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
read-logs
description
This skill should be used whenever the user wants to read, tail, stream, or search Dokploy logs — application runtime logs, Docker Compose stack logs (every container), database logs, or deployment build logs — and especially to diagnose why something failed. Triggers: "read the logs", "show me the dokploy logs", "tail the logs", "compose logs", "all containers' logs", "container logs", "why is my app crashing", "why did my deploy fail — check the logs", "grep the logs for an error", "runtime logs", "build logs". Use it instead of telling the user logs aren't available over the API — since Dokploy v0.29.0 they are.
# Read Dokploy Logs (runtime + build, every container) Dokploy (since **v0.29.0**; current **v0.30.7**) exposes container logs over the REST API and the `@dokploy/mcp` server. There are four log sources, each with its own tool. The single most common mistake — and the reason multi-container Compose debugging fails — is calling `compose-readLogs` **without a `containerId`**. A Compose stack has many containers; you must enumerate them and read each one. > **Do not** tell the user "Dokploy doesn't expose runtime logs via REST / use SSH or Beszel." That was true before [issue #3719](https://github.com/Dokploy/dokploy/issues/3719) was resolved. Since v0.29.0, `application-readLogs`, `compose-readLogs`, and every `{db}-readLogs` return **live container stdout/stderr** with `tail` / `since` / `search` filtering. SSH/Beszel is a last resort only (container not Dokploy-managed, or API unreachable). --- ## Step 0 — Decide which log you need ``` What are you debugging? ├─ The BUILD failed (image never built) → deployment build log → §3 ├─ A standalone APP is crashing / erroring → application runtime log → §1 ├─ A COMPOSE stack (multi-container) → per-container loop → §2 ← the important one └─ A DATABASE service → database runtime log → §4 Then optionally hand the text to AI triage → §5 ``` All runtime-log tools share three optional filters: | Param | Meaning | Values | |---|---|---| | `tail` | How many recent lines | integer `1`–`10000` (default `100`). Use `1000`+ when hunting an intermittent error | | `since` | Time window | `all` (default) or `<n><unit>` where unit ∈ `s m h d` — e.g. `30s`, `15m`, `2h`, `7d` | | `search` | Substring filter (server-side grep) | up to 500 chars, limited to letters, digits, space, `.`, `_` and `-` (so `ECONNREFUSED` works, `ECONNREFUSED 10.0.0.5:5432` does not — drop the colon), e.g. `search: "error"` | --- ## §1 — Application runtime logs A standalone application is one container. Read it directly: ``` mcp__plugin_dokploy-dev_dokploy__application-readLogs → { applicationId: "<id>", tail: 200, since: "1h", search?: "error" } ``` - Get `applicationId` from `application-one` / `application-search` / `project-all`. - Returns the container's stdout/stderr. If it's empty, the container may not be running — check state with `docker-getContainersByAppLabel { appName, type: "standalone" }` (note: `type` is **required**; use `"swarm"` for cluster apps). --- ## §2 — Compose stack: read EVERY container This is the workflow the user means by "read all the logs of all containers." A Compose stack runs N services; `compose-readLogs` is **per container** (`containerId` is required), so you must enumerate first, then loop. **1. Resolve the stack identity.** ``` mcp__plugin_dokploy-dev_dokploy__compose-one → { composeId: "<id>" } ↳ read .appName (the Docker name prefix Dokploy assigns) ↳ read .composeType ("docker-compose" | "stack") ``` (If you only have a name, find the `composeId` with `compose-search { q: "<name>" }`.) **2. Enumerate the containers** — pick the discovery tool by `composeType`: | `composeType` | Discovery tool | Call | |---|---|---| | `docker-compose` | `docker-getContainersByAppNameMatch` | `{ appName, appType: "docker-compose" }` | | `stack` (Swarm) | `docker-getStackContainersByAppName` | `{ appName }` | | _unsure / fallback_ | `docker-getContainers` then filter by name containing `appName` | `{}` (lists all host containers) | Each returned container is `{ containerId, name, state, status }` — e.g. `{ containerId: "a1b2c3d4e5f6", name: "my-stack-ab12cd-app-1", state: "running", status: "Up 5 days (healthy)" }`. **Save the `containerId` of every container** (the short Docker id) — that's what you pass next. Note which containers are `exited` / `restarting` / unhealthy; those are your prime suspects. **3. Read logs for EACH container** (loop — do not stop at the first): ``` for each container c in the enumerated list: mcp__plugin_dokploy-dev_dokploy__compose-readLogs → { composeId: "<id>", containerId: c.containerId, tail: 200, since: "1h", search?: "error" } ``` The response `.data` is a single newline-joined string where each line is prefixed with an RFC3339 timestamp, e.g. `2026-06-04T09:14:16.979Z Error: Failed to find Server Action ...`. Split on `\n` and scan the tail for the §6 patterns. **4. Aggregate and diagnose.** Print one section per container (`### <service/containerId> — <state>`), surface error lines first (see §6 patterns), and call out the container(s) that are down. A stack is only as healthy as its sickest container — a crashed `db` container makes the `web` container throw `ECONNREFUSED`, so reading *all* of them is what reveals the real root cause. The `/dokploy-dev:compose-logs <compose>` command runs this entire loop for you. --- ## §3 — Deployment (build) logs The build log explains why an image failed to build (before any container starts). ``` 1. Find the deployment: mcp__plugin_dokploy-dev_dokploy__deployment-all { applicationId } # or { composeId } / { serverId } mcp__plugin_dokploy-dev_dokploy__deployment-allCentralized # if you don't know which resource ↳ pick the most recent row with status: "error"; save deploymentId 2. Read it: mcp__plugin_dokploy-dev_dokploy__deployment-readLogs { deploymentId: "<id>", tail: 500 } ``` `deployment-readLogs` takes only `deploymentId` + `tail` (no `since`/`search` — it's one finite artifact). Use this for build-time failures; use §1/§2 for run-time failures. > **If `deployment-readLogs` is not a registered tool in your session, read the build log over REST instead — do not conclude it's unavailable.** Some MCP builds expose only a subset of Dokploy's endpoints, so the tool list / `ToolSearch` won't find `deployment-readLogs` even though the instance (v0.29.0+) serves it. The REST endpoint is always there: > ```bash > curl -s -G "$DOKPLOY_URL/api/deployment.readLogs" \ > -H "x-api-key: $DOKPLOY_API_KEY" \ > --data-urlencode "deploymentId=<id>" --data-urlencode "tail=500" > ``` > Build logs carry `\r` progress noise — pipe through `tr '\r' '\n'` before grepping. The response is a JSON string. This MCP-tool-missing → REST-fallback move works for any endpoint; confirm exact paths/params in the `api-reference` indexes (or fetch the OpenAPI document over REST — `GET /api/settings.getOpenApiDocument`; the MCP tool returns 27 operations as `[REDACTED]` by default). The CLI is an equivalent fallback: `dokploy deployment read-logs --deploymentId <id> --tail 500` (same endpoint, no curl quoting). Diagnosing a build failure from indirect signals when the real log is one `curl` away leads to wrong root causes. --- ## §4 — Database runtime logs Each database type has its own `readLogs` with the same filters: ``` mcp__plugin_dokploy-dev_dokploy__postgres-readLogs { postgresId, tail, since, search } mcp__plugin_dokploy-dev_dokploy__mysql-readLogs { mysqlId, tail, since, search } mcp__plugin_dokploy-dev_dokploy__mariadb-readLogs { mariadbId, tail, since, search } mcp__plugin_dokploy-dev_dokploy__mongo-readLogs { mongoId, tail, since, search } mcp__plugin_dokploy-dev_dokploy__redis-readLogs { redisId, tail, since, search } mcp__plugin_dokploy-dev_dokploy__libsql-readLogs { libsqlId, tail, since, search } ``` Get the id from `{type}-one` / `{type}-search`. Typical hunts: `search: "FATAL"` (Postgres auth/startup), `search: "Out of memory"`, `search: "Access denied"` (MySQL/MariaDB creds). --- ## §5 — Hand the logs to AI triage (optional) If an AI provider is configured, let it summarize the text you just fetched. **`ai-analyzeLogs` does NOT take a `deploymentId`** — you pass the actual log text: ``` 1. aiId = first enabled provider from mcp__plugin_dokploy-dev_dokploy__ai-getEnabledProviders (if empty → AI not configured; skip, or wire one up via the ai-assist skill) 2. logs = the log text returned by readLogs in §1–§4 (truncate very large logs) 3. context = "build" for §3 deployment logs "runtime" for §1 / §2 / §4 logs mcp__plugin_dokploy-dev_dokploy__ai-analyzeLogs → { aiId, logs, context } ↳ returns a natural-language root cause + suggested fix ``` See the `ai-assist` skill for provider setup. Read the AI's answer critically — it only sees the log you gave it, not the codebase. --- ## §6 — Error patterns to surface first When formatting any log output, grep (case-insensitive) for these and show matching lines at the top: | Signal | Likely meaning | |---|---| | `error`, `fatal`, `panic`, `traceback`, `exception` | application-level failure | | `exited`, `exit code`, `killed`, `OOMKilled`, `out of memory` | container died / resource limit | | `ECONNREFUSED`, `connection refused`, `getaddrinfo`, `ENOTFOUND` | service can't reach a dependency (DB/cache/another container) | | `denied`, `unauthorized`, `403`, `401`, `authentication failed` | credential / token problem | | `no space left on device` | disk full → run `/dokploy-dev:cleanup` | | `EADDRINUSE`, `address already in use`, `bind` | port collision | | `timeout`, `timed out`, `deadline exceeded` | slow dependency / health-check failing | If you find one, suggest the next step: `/dokploy-dev:analyze` (AI triage) or `/dokploy-dev:debug <id>` (full decision tree). --- ## §7 — Last resort (only if the API can't serve the log) Use these **only** when a container is not managed by Dokploy, or the Dokploy API itself is unreachable: - SSH to the server: `docker logs --tail 500 <containerId>` (get `<containerId>` from `docker-getContainers`). - Beszel, if installed, can read the on-disk log files under `/etc/dokploy/logs/<appName>/`. These are fallbacks, not the default. For any Dokploy-managed app/compose/database, §1–§4 are the correct path. --- ## Examples <example> User: "My app `web-api` keeps restarting — show me what's wrong." 1. `application-one { applicationId }` (or resolve via `application-search { q: "web-api" }`) → confirm it exists, grab `appName`. 2. `application-readLogs { applicationId, tail: 300, since: "30m" }`. 3. Grep the result: a `panic: runtime error: invalid memory address` line appears near the end. 4. Report the panic + stack frame, note the crash loop, and offer `/dokploy-dev:analyze` for an AI root-cause. </example> <example> User: "Read all the logs for my `n8n-stack` compose project, something's broken." 1. `compose-search { q: "n8n-stack" }` → `composeId`; `compose-one { composeId }` → `appName: "n8n-stack-xxxx"`, `composeType: "docker-compose"`. 2. `docker-getContainersByAppNameMatch { appName: "n8n-stack-xxxx", appType: "docker-compose" }` → 3 containers: `n8n` (running), `postgres` (restarting), `redis` (running). 3. Loop `compose-readLogs { composeId, containerId, tail: 200 }` for ALL THREE. 4. The `postgres` container log shows `FATAL: database files are incompatible with server`. The `n8n` log shows `ECONNREFUSED postgres:5432` — a downstream symptom. Report postgres as the root cause; n8n is fine once the DB is fixed. </example> <example> User: "Why did the last deploy of `landing` fail?" 1. `deployment-all { applicationId }` → most recent row `status: "error"`, save `deploymentId`. 2. `deployment-readLogs { deploymentId, tail: 500 }`. 3. Log shows `error: failed to solve: failed to read dockerfile`. Report: wrong `dockerContextPath` / missing Dockerfile; fix via `application-saveBuildType` then `application-redeploy`. </example> --- ## See also - `/dokploy-dev:compose-logs <compose>` — one-shot "read every container" command (this skill's §2, automated) - `/dokploy-dev:logs <resource>` — unified single-resource log reader - [`debug-deploy`](../debug-deploy/SKILL.md) — full failure decision tree (uses these log calls) - [`ai-assist`](../ai-assist/SKILL.md) — configure a provider for `ai-analyzeLogs`
View on GitHub