Dokploy / Dokploy/dokploy

[Bug] Worker nodes get providers.swarm in Traefik config → endless "not a swarm manager" retry loop floods logs until disk fills

Open
#5,112 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
37.4k
Forks
3k
Avg merge
1d 3h
Merged PRs (30d)
73

Description

Summary

On a Docker Swarm cluster where Traefik runs as the per-node standalone container, Dokploy writes a default traefik.yml with providers.swarm enabled to every node — including worker nodes — even though the Swarm provider can never work on a non-manager. The resulting infinite retry loop floods Traefik's container log and the daemon journal/syslog until disk fills.

Environment
  • Dokploy server dokploy/dokploy:v0.30.0 (also verified on latest upstream ded23bb, Aug 17 2026)
  • Docker Swarm cluster, server running as a Swarm service on the manager node; 1 manager + 2 workers
  • Traefik traefik:v3.6.7 as a standalone dokploy-traefik container on each node (verified via docker inspect; not a Swarm service)
To Reproduce
  1. Stand up a Dokploy Swarm cluster with ≥1 worker node; add the worker in Dokploy.
  2. cat /etc/dokploy/traefik/traefik.yml on the worker → providers.swarm is present.
  3. docker logs -f dokploy-traefik on the worker → repeated
    Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. while retrying forever (backoff ~0.6–3s).
  4. Leave it running; the container json log (and the daemon journal/syslog) grow without bound.
Expected behavior

The Swarm provider should not be enabled (or Traefik not scheduled) on nodes that cannot serve the Swarm API, so no guaranteed-failure retry loop and no unbounded log growth.

Current behavior

Observed on a real cluster: worker dokploy-traefik container logs reached 1.5 G each (two workers), and syslog.1 reached 2.5 G (~17,800 repetitions), ≈ 5.5 G before mitigation.

Each failed poll is written twice: into the container json log and into the daemon journal (→ syslog).

Root cause (verified in source)

packages/server/src/setup/traefik-setup.ts:

  • getDefaultTraefikConfig() (:253) — its production branch (around :265) emits providers.swarm unconditionally:

    : { swarm: { exposedByDefault: false, watch: true },
        docker: { exposedByDefault: false, watch: true, network: "dokploy-network" } }
    

    There is no isManager/node-role check in this path.

  • getDefaultServerTraefikConfig() (:~322) does the same (providers.swarm at :326).

  • createDefaultTraefikConfig() (:377) writes that config to <MAIN_TRAEFIK_PATH>/traefik.yml (i.e. /etc/dokploy/traefik/traefik.yml), early-returning only if the file already exists. It runs at every Dokploy bootstrap on any node running the Dokploy app/agent (apps/dokploy/server/server.ts:35, apps/dokploy/setup.ts:27).

  • The standalone Traefik deployed per node initializeStandaloneTraefik() (:35) has no placement constraint and binds the local socket plus that config.

Contrast: the Swarm-service variant initializeTraefikService() (:150+) does correctly constrain Traefik to managers:

Placement: { Constraints: ["node.role==manager"] },

So the defect is specific to the standalone per-node path: it neither constrains Traefik to the manager nor strips the Swarm provider from worker configs. On a worker, GET /services is a manager-only API, so the loop is guaranteed and permanent.

Suggested fix

Make Swarm-provider inclusion role-aware, least→most invasive:

  1. In createDefaultTraefikConfig/getDefaultTraefikConfig, detect whether the local node is a Swarm manager (e.g. docker infoSwarm.LocalNodeState + Swarm.ControlAvailable) and omit providers.swarm when not a manager.
  2. Apply a node.role==manager placement constraint to standalone Traefik in initializeStandaloneTraefik when in Swarm mode (mirrors the already-correct initializeTraefikService).
  3. Add a per-node/settings toggle for which providers Traefik enables, defaulting sensibly per node role.
Related

Different from — but in the same Swarm/Traefik/log space: #4835 (daemon CPU from stale log readers), #4519 (database deploy failing with this error), #3516 (database backup on worker).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/server/src/setup/traefik-setup.ts, especially getDefaultTraefikConfig(), getDefaultServerTraefikConfig(), createDefaultTraefikConfig(), initializeStandaloneTraefik(), and initializeTraefikService(). Compare the existing manager placement constraint with the standalone path, then inspect apps/dokploy/server/server.ts and apps/dokploy/setup.ts for bootstrap behavior. Done means worker nodes no longer enable or run a Swarm provider in the standalone path, while manager behavior remains functional and the retry loop is prevented.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, typescript
Domain
devops, infrastructure
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.