Skip to content

Domain-linked compose service on two networks makes Traefik route to a stale/wrong IP — 502 that doesn't self-heal (restart/reload insufficient, only container recreate fixes it) #4807

Description

@myagizmaktav

Summary

When a domain is attached to a Docker Compose service, addDokployNetworkToService (packages/server/src/utils/docker/domain.ts) unconditionally attaches that service to both dokploy-network and the project's implicit default network — this was the intentional fix for #3562 (services losing connectivity to siblings). In a live production incident, this dual-network attachment caused Traefik's Docker provider to select the wrong network's IP for the domain-linked service, producing a persistent 502 Bad Gateway that did not self-heal.

Reproduction / live incident

  • App: a single-service (well, two-service: web + a healthcheck-watchdog sidecar) Compose deployment, web has a domain attached.
  • web's own docker-compose.yml only declares networks: [dokploy-network] for the service.
  • After a deploy, the site started returning 502 Bad Gateway through Cloudflare → Traefik.
  • Docker's own HEALTHCHECK reported the container as healthy the entire time (confirmed via docker.getConfig/docker.getContainers through the Dokploy API) — the app itself was fine and responding on 127.0.0.1:3000 inside the container.
  • docker.restartContainer (same container ID) did not fix external routing — container came back healthy, site still 502.
  • Dokploy's settings.reloadTraefik also did not fix it.
  • Inspecting the running container (docker.getConfig) showed it attached to two networks:
    "Networks": {
      "dokploy-network": { "IPAddress": "10.0.1.121", ... },
      "<appName>_default": { "IPAddress": "172.22.0.2", ... }
    }
    even though the user's own compose file never references a default network at all.
  • The only thing that fixed it: fully removing the container (docker.removeContainer) and triggering a fresh compose.deploy (new container ID, new network endpoint registration). This matches the pattern already reported in Compose deployments: Traefik routing broken - containers not added to dokploy-network #3435 and the general Traefik-multi-network class of issues (Docker container w. multiple networks, route to wrong IP traefik/traefik#1156, #9551, Traefik v2 routes to wrong Ip, service in 2 networks traefik/traefik#5657).

Root cause (confirmed in current canary source)

packages/server/src/utils/docker/domain.ts:

export const addDokployNetworkToService = (
  networkService: DefinitionsService["networks"],
) => {
  let networks = networkService;
  const network = "dokploy-network";
  const defaultNetwork = "default";
  ...
  if (Array.isArray(networks)) {
    if (!networks.includes(network)) {
      networks.push(network);
    }
    if (!networks.includes(defaultNetwork)) {
      networks.push(defaultNetwork); // <-- always added, unconditionally
    }
  }
  ...
};

This is intentional (per @Siumauricio's comment on #3562: "I think it's a good idea to add the default network to the service where it is specified that the domain should be added"), and is covered by an existing test (apps/dokploy/__test__/compose/domain/network-service.test.ts) that explicitly asserts addDokployNetworkToService(["dokploy-network"])["dokploy-network", "default"].

The tension: this fix for #3562 (keep sibling-service connectivity via the default network) reintroduces the exact multi-network ambiguity that can make Traefik's Docker provider pick the wrong backend IP for the domain-linked service — for compose apps that don't actually need default-network connectivity (single-service apps, or apps managing their own explicit network topology), this default-on behavior has no upside and a real downside (persistent, non-self-healing 502s).

Proposed fix

I've opened a PR (#TODO — filled in after creation) adding an opt-in, backward-compatible per-domain flag skipDefaultNetwork (default false, so all existing behavior/tests are unchanged) that lets a domain skip the default network attachment while still keeping dokploy-network. All existing tests pass unchanged; 5 new tests added for the opt-in path. Happy to adjust the exact API/naming/whether this should live on Domain vs Compose per your preference — this is meant as a starting point for discussion, not a final word on the design.

Environment

  • Dokploy version: v0.29.11 (current canary as of 2026-07-12)
  • Deployment type: Docker Compose (not Swarm/Application)
  • Same server where Dokploy is installed

Will you send a PR to fix it?

Yes — see linked PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions