Leave a Docker Swarm Node Without Losing Manager Quorum
docker swarm leave pulls one node out of its cluster, and run on the wrong manager it can strand the rest below quorum. A worker leaves in about fifteen minutes. A manager needs a maintenance window and a second, healthy manager standing by. Examples use Docker CE CLI 29.8.1, package version 5:29.8.1-1~ubuntu.24.04~noble, installed on this machine.
The route
Jump straight to the step you need, or tick off Done means at the end.
Warning
docker swarm leave changes cluster membership on the node where it runs. Do not use --force as a routine confirmation prompt. On a manager it can leave the remaining swarm without enough managers to accept administrative changes.
1. Check the command and the local swarm state
First confirm the installed syntax. This is an ordinary, read-only check and normally needs no elevated privilege:
$ docker version --format '{{.Client.Version}}'
29.8.1
$ docker swarm leave --help
Usage: docker swarm leave [OPTIONS]
Leave the swarm
Options:
-f, --force Force this node to leave the swarm, ignoring warnings
Then ask the local Docker Engine whether this host belongs to a swarm:
$ docker info --format 'Swarm={{.Swarm.LocalNodeState}} Control={{.Swarm.ControlAvailable}}'
Swarm=active Control=false
- Active means joined.
LocalNodeState=activemeans this Engine is in a swarm;inactivemeans there is nothing local to leave. - False means worker.
Control=falseidentifies a worker here; a manager normally reportsControl=true. - Skip sudo. Add it only if your Docker socket permissions actually require it, and fix ordinary group or service-account access through your normal administration process rather than reaching for it by habit.
Checkpoint
Stop if the state is not what you expected. Check the Docker context too, because a command can quietly target a remote Engine rather than the host in front of you:
$ docker context show
default
2. Leave a worker from that worker
A worker can leave by running the command locally. Run it on the node being retired, not on a different manager:
$ docker swarm leave
Node left the default swarm.
The swarm name in the message can differ from default. What matters is a clean exit and that message. Verify the local state:
$ docker info --format 'Swarm={{.Swarm.LocalNodeState}} Control={{.Swarm.ControlAvailable}}'
Swarm=inactive Control=false
Leaving does not scrub every record of the node from a manager's memory. From a manager, docker node ls may keep showing it as down: that stale entry is not proof the worker is still participating. If it is just clutter, an administrator can remove it with docker node rm NODE_ID from a manager, after checking the exact node ID. That is a separate cluster operation.
There is no undo command for a completed leave. To put the machine back, get a fresh worker join command from a manager and run it there, for example:
$ docker swarm join --token <WORKER_JOIN_TOKEN> <MANAGER_HOST>:2377
This node joined a swarm as a worker.
Keep the token private. If it has been exposed, rotate the worker join token from a manager before reusing it.
3. Inspect a manager before touching it
Managers store and replicate swarm state, so a manager should normally be demoted before it leaves. Run these checks from a manager, where docker node ls is available:
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
<THIS_NODE_ID> manager-a Ready Active Leader
<OTHER_NODE_ID> manager-b Ready Active Reachable
<WORKER_NODE_ID> worker-a Ready Active
$ docker node inspect <THIS_NODE_ID> --format '{{.ManagerStatus.Reachability}}'
reachable
Replace the placeholders with the real values, and do not guess manager health from the hostname alone. Count the manager rows and confirm another reachable manager can perform the next command: Raft needs a majority. A three-manager swarm needs two available, so losing one is normally fine, but losing a second before the first change settles is not.
If the node you want gone is the only manager, do not use --force just to make the warning go away. A single-node swarm has no manager redundancy. Decide first whether the whole swarm is being retired or another node will be promoted, and keep any required service and swarm backups current.
4. Demote the manager, then leave it
From another healthy manager, demote the target to a worker:
$ docker node demote <TARGET_MANAGER_ID_OR_NAME>
Manager <TARGET_MANAGER_ID_OR_NAME> demoted in the swarm.
Verify the target has lost its manager status before you connect to it:
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
<TARGET_NODE_ID> manager-a Ready Active
<OTHER_NODE_ID> manager-b Ready Active Leader
Now connect to the target machine and run the ordinary worker leave from step 2. Demotion changes its role in the swarm; leaving removes its local membership. If the target is also running service tasks, plan for those to be rescheduled and check placement afterwards.
Warning
Do not run docker swarm leave --force on a manager unless it is being abandoned or the swarm itself is being dismantled, such as a single-node test swarm. A force leave ignores the warning instead of repairing quorum, and can strand the remaining managers below a majority: existing tasks keep running while administrative operations fail. Removing an unreachable manager from an otherwise healthy swarm needs the manager-side removal and recovery procedure for that failure, not a guessed command on the failed host.
5. Diagnose a failed leave without repeating the damage
- Says it is not part of a swarm. Inspect
docker infoand the active context. An inactive local state means the leave already happened, or you are on the wrong Engine. Do not retry with--force. - Warns that a manager must be demoted. Go back to step 3 and use another reachable manager. If there is no reachable majority, stop making membership changes: workers can keep running, but the swarm cannot reliably process management requests until quorum is back. Treat a timeout as an incident, not permission to fire off several force commands.
- Fails to reach the daemon or socket. Check the service and permissions without changing swarm state:
$ docker info --format '{{.ServerVersion}}'
29.8.1
$ systemctl is-active docker
active
Use sudo systemctl is-active docker only when your account cannot query the service. Restarting Docker is not part of a normal leave and can disrupt workloads, so schedule that separately if diagnostics point to a daemon problem.
Done means
- Context checked. You confirmed the Docker context and the target Engine's swarm state before doing anything.
- Worker leave verified. It left with
docker swarm leaveand now reportsSwarm=inactive. - Manager quorum protected. A manager was inspected for quorum and demoted from another healthy manager first.
- Force reserved. You used
--forceonly for an explicitly abandoned manager or swarm. - Recovery path known. Leaving has no local undo, but you have a controlled join-token route back in.