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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions