Skip to content

Docker-image apps: any deploy (webhook or API) rewrites the Swarm service spec and drops the app's traefik.* labels → all domains 404 #5453

Open

Description

@findingpatterns

Environment

  • Dokploy v0.29.12 (original) and v0.30.6 (after upgrading — still reproduces)
  • Self-hosted on a single-node Docker Swarm (Ubuntu arm64 VM), Traefik as shipped by Dokploy (docker provider, @docker routers)
  • Affected applications are sourceType=docker with a pinned dockerImage (ghcr.io/<org>/<app>:vX.Y.Z), domains added through the Domains tab (one app has 4 hostnames, another has 1), https: true, certificateType: letsencrypt

Summary

Any deploy rewrites the application's Swarm service spec without its traefik.* labels. After the deploy the containers are healthy ("✓ Ready") but Traefik has no router for the app's domains, so every hostname returns Traefik's plain-text 404 page not found.

Reproduced on both deploy entry points:

Deploy path Labels before Labels after
POST /api/deploy/<refreshToken> (webhook, called by CI) 9 0
POST /api/application.deploy + x-api-key 9 0

Both apps (4 domains and 1 domain) are affected; measured 3 times in total, on v0.29.12 and again on v0.30.6.

Evidence

Before a deploy:

$ docker service inspect omt-frontend-31cc8b --format '{{json .Spec.Labels}}'
{"traefik.enable":"true",
 "traefik.http.routers.<app>-web.entrypoints":"web",
 "traefik.http.routers.<app>-web.rule":"Host(\"app.example.com\") || Host(\"accounts.example.com\") || …",
 "traefik.http.routers.<app>-web.service":"omt-frontend",
 "traefik.http.routers.<app>-websecure.entrypoints":"websecure",
 "traefik.http.routers.<app>-websecure.rule":"Host(…)",
 "traefik.http.routers.<app>-websecure.service":"omt-frontend",
 "traefik.http.routers.<app>-websecure.tls":"true",
 "traefik.http.services.omt-frontend.loadbalancer.server.port":"3000"}

After the deploy (service UpdatedAt matches the deployment time, new task Running, same image digest):

$ docker service inspect omt-frontend-31cc8b --format '{{json .Spec.Labels}}'
{}

$ docker service inspect omt-frontend-31cc8b --format '{{len .PreviousSpec.Labels}}'
9      # the labels still exist in PreviousSpec ⇒ the update removed them

The deployment log only contains the image pull step:

Initializing deployment
Pulling ghcr.io/…:v1.2.45
Login Succeeded
Status: Image is up to date for ghcr.io/…:v1.2.45
✅ Pulling image completed.

(the service update that drops the labels is not logged)

Steps to reproduce

  1. Create an application with sourceType=docker, a registry image and a domain (port 3000, https).
  2. Deploy once and confirm the router works (curl -I https://<domain> → 200, Spec.Labels has the 9 traefik.* entries).
  3. Deploy again from either entry point (webhook or application.deploy).
  4. After the task restarts: Spec.Labels is {}, PreviousSpec.Labels still has them, and every domain of that app returns Traefik's 404.

Impact

CI that deploys on push (or any API automation / UI redeploy) takes the app offline routing-wise until the labels are restored by hand, while the container itself stays up — so health checks and Dokploy's own deployment status still report success.

Workaround we run now

A systemd timer on the Docker host that re-adds the label set whenever traefik.enable is missing from the service (15 s cycle). docker service update --rollback <service> also restores the labels (it reverts the previous spec) but that also rolls the image back to the previous tag.

Context that may or may not matter

Both affected applications were created by duplicating a project (project duplicate --includeServices + application move) on an older Dokploy; in the DB their application.refreshToken was empty (we had to set it) and autoDeploy was false. registryId is null on both (the images are pulled with node-level credentials). Happy to dump the application / domain rows or full specs if that helps.

Activity

  1. linear-code commented on Sep 13, 2026

    @linear-code
  2. SebZbp commented on Sep 21, 2026

    @SebZbp

    Possibly related data point from the Compose side — I hit what looks like the same class of regression upgrading from 0.29.x to 0.30.x (I don't recall the exact 0.29 patch; I'm on 0.30.6 now).

    In my case it's a Docker Compose service, not a docker-image app: custom traefik.* labels declared in my docker-compose.yml are no longer honoured once a domain is configured on the service. Before the upgrade my own labels took effect; now the domain-generated config wins and my labels are effectively ignored.

    The common thread with this issue seems to be that the deploy path regenerates the full Traefik config/spec rather than merging with what's already declared — same shape as #4243 and #5018, and as described in #4415 about manageDomain() always regenerating with no merge capability.

    Happy to open a separate Compose-specific issue if you'd prefer to keep this one scoped to Swarm docker-image apps — just say so.

  3. SebZbp commented on Sep 21, 2026

    @SebZbp

    Related to #5495

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions