Rolling replace for Docker Compose services

A normal Compose redeploy stops and removes the old container and only then starts the new one, so a changed service has a window with no backend. Rolling replace is an opt-in setting of Dokploy Community Edition that changes the order for the services you select: the new replica must pass its healthcheck before the old container is stopped. Upstream Dokploy v0.30.8 has no such option. It is off by default and nothing changes until you turn it on for a service.

See also the home page, the FAQ and the deploy queue controls.

What happens on a deploy

For each selected service:

  1. The new image is built or pulled first. Nothing running is touched.
  2. New replicas start from the new release next to the old ones: one for a single-container service, N for a service with deploy.replicas: N.
  3. Dokploy waits until every new replica is healthy, up to the health timeout.
  4. The old containers are taken out of rotation and, after the drain delay, stopped and removed by id.

If a new replica never becomes healthy, all new replicas are removed and the old containers, which were never touched, keep serving. The deployment is marked as an error and the usual failure notification is sent. Services you did not select are deployed as before. A selected service whose configuration and image did not change is left running.

Turn it on

Open the Compose service, go to the Advanced tab and find the Rolling replace card.

  1. Enable it.
  2. Pick the services to roll. The list shows which services are eligible and why a service is not. You pick services explicitly; there is no “all”.
  3. Optionally set the health timeout (10 to 900 seconds, default 120). Dokploy raises it at deploy time when the service’s healthcheck needs longer, up to 900.
  4. Optionally set the drain delay (0 to 120 seconds, default 5), the wait between “new replica healthy” and “stop the old container”.

It applies to docker-compose type services without a custom command, and not to fresh-volumes deploys. Compose previews never roll.

Which services are eligible

A service is refused when it:

Variables such as deploy.replicas: ${WEB_REPLICAS:-1} are resolved first, with the variables Dokploy writes to the deploy’s .env; the deployed compose file is not changed. When a value cannot be known (an unset :? variable, a vault reference that cannot be resolved, no Create env file), the service is judged on the file as written and the deploy log says so.

Eligibility is checked when you save and again at every deploy. If a selected service stops being eligible, it is recreated the normal way with a note in the deploy log, and the deploy is not failed for that.

Things only you can check

During the overlap two copies of the service run. Decide first whether that is safe for the service:

Container-to-container traffic by service name can reach both replicas during the overlap.

Cancel and failure behavior

Cancelling a rolling deploy removes the replicas that were not promoted yet and leaves the old containers serving. If the old container cannot be removed after the new one is healthy, the service reports a failure, the new replica keeps serving, and the next deploy reconciles the leftover. When several services are selected, services already replaced stay on the new release; there is no automatic revert of those.

Add a Traefik retry yourself

Traefik drops the old backend only when the container dies, so requests can still reach it during its stop grace period. Dokploy does not inject a middleware for this. Add a retry middleware once, by hand, and attach it to the domain:

http:
  middlewares:
    rolling-retry:
      retry:
        attempts: 3
        initialInterval: 100ms

Save it as /etc/dokploy/traefik/dynamic/rolling-retry.yml on the host and add rolling-retry@file to the domain’s custom middlewares. A retry covers connection errors and short blips, not a long outage.

Swarm stacks

Rolling replace does not apply to Compose stacks of type stack. For those, put a healthcheck in the compose file and set deploy.update_config.order: start-first with failure_action: rollback, which gives the same start-before-stop behavior through Docker Swarm.

Limits

Source