Safely Inspect and Maintain Docker Swarm Nodes
A single command, docker node, lists every Swarm node, inspects one, drains it for maintenance, and can add or remove control-plane managers. This guide walks through identifying nodes, reading their state, running a maintenance drain, and making a controlled membership change. Allow about 15 minutes for inspection and a maintenance drain; removing a node or changing a manager role needs a maintenance plan and a recovery path.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide uses Docker CE CLI 29.8.1, installed here as package docker-ce-cli version 5:29.8.1-1~ubuntu.24.04~noble. The local docker-node(1) page is the umbrella entry for the command; its subcommand help lists the installed option set. Run these commands from a Swarm manager, and confirm your Docker context before you affect a real cluster, since most Docker commands act on whichever context is currently selected.
1. Confirm the target context and command set
Start with read-only checks. Do not add sudo automatically: use it only if your local Docker socket policy requires elevated access, and understand that it changes which Docker configuration and context may be used.
$ docker version --format '{{.Client.Version}}'
29.8.1
$ docker node --help
Usage: docker node COMMAND
Manage Swarm nodes
The available subcommands are ls, inspect, ps, update, promote, demote and rm. If Docker reports that the node is not a manager, stop here: a worker can run workloads, but node administration is a manager operation.
Checkpoint
You have confirmed the Docker context and are connected to the intended manager. If you use named contexts, run docker context show and record the result before continuing.
2. List nodes and filter the view
List the nodes the manager knows about. The command prints a table containing the node ID, hostname, readiness, availability and manager status.
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
MANAGER-ID * manager-1 Ready Active Leader
WORKER-ID worker-1 Ready Active
$ docker node ls --filter role=worker
$ docker node ls --quiet
MANAGER-ID
WORKER-ID
The asterisk identifies the node used by the current Docker daemon; it does not mean that node is the leader. The supported filters include id, label, node.label, membership, name and role. Quote a filter containing shell punctuation, such as --filter "role=manager".
For scripts, request JSON records or a small template rather than parsing aligned columns:
$ docker node ls --format json
{"Availability":"Active","EngineVersion":"ENGINE-VERSION","Hostname":"HOSTNAME","ID":"NODE-ID","ManagerStatus":"Leader","Self":true,"Status":"Ready","TLSStatus":"Ready"}
3. Inspect one node before changing it
Use inspect when the summary is not enough. The default result is a JSON array, useful for retaining the exact state before maintenance. The --pretty option gives a human-readable view instead.
$ docker node inspect --pretty NODE-NAME-OR-ID
ID: NODE-ID
Hostname: HOSTNAME
Status:
State: Ready
Availability: Active
Manager Status: Reachable
Exact fields and manager status vary with the node, so treat the values above as a shape, not a promised transcript. Save a read-only record when you need an audit trail:
$ docker node inspect NODE-NAME-OR-ID > node-before.json
Do not publish that file casually. Node inspection can expose infrastructure details, so keep it in a suitably protected directory and remove it according to your organisation's retention rules once it is no longer needed.
4. See the tasks before planned maintenance
Before draining a node, find the Swarm tasks assigned to it:
$ docker node ps NODE-NAME-OR-ID
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE
TASK-ID SERVICE.1 IMAGE HOSTNAME Running Running
$ docker node ps NODE-NAME-OR-ID --no-trunc
docker node ps defaults to the current node if you omit the node argument. That default is a common distraction trap: an apparently empty result may describe the manager you are connected to, not the worker you meant to maintain. Use the explicit node name or ID in operational notes and scripts.
5. Drain a node for maintenance
Warning
Draining changes scheduling and can stop running Swarm service tasks on that node. The manager attempts to replace them on available nodes, so check capacity, replicas and any placement constraints first. Standalone containers created with docker run or Compose are not moved by this setting.
Change the node's availability from active to drain:
$ docker node update --availability drain NODE-NAME-OR-ID
NODE-NAME-OR-ID
Verify the change and watch service placement:
$ docker node inspect --pretty NODE-NAME-OR-ID
Availability: Drain
$ docker node ps NODE-NAME-OR-ID
$ docker service ps SERVICE-NAME
When maintenance is complete, restore scheduling explicitly:
$ docker node update --availability active NODE-NAME-OR-ID
NODE-NAME-OR-ID
Checkpoint
The node is Drain while it is being serviced, and returns to Active only after you have checked the host. Drain is reversible, but it is not a harmless label: service tasks may be recreated elsewhere.
6. Add labels or change a role carefully
Node labels are Swarm metadata used by service placement constraints, and they are not the same as Docker daemon labels:
$ docker node update --label-add type=queue NODE-NAME-OR-ID
$ docker node inspect NODE-NAME-OR-ID --pretty
Remove a label only when you have checked that no service constraint depends on it:
$ docker node update --label-rm type NODE-NAME-OR-ID
Warning
Promotion and demotion alter the control plane, not just workload placement. A worker can be promoted with docker node promote; a manager can be demoted with docker node demote. Keep manager quorum in mind, and do not demote the last viable manager as a routine maintenance step.
7. Remove a node only after membership is settled
Removal is a membership change, not a way to tidy a display. First inspect the node and confirm that it is down, or that you have deliberately accepted the consequences of force removal.
$ docker node inspect --pretty NODE-NAME-OR-ID
$ docker node rm NODE-NAME-OR-ID
Normal removal is intended for a stopped or down node. If an inaccessible worker must be removed, --force exists, but it can interrupt tasks and should be treated as an incident action:
$ docker node rm --force UNREACHABLE-WORKER-ID
A manager must be demoted before removal. There is no undo command that restores the old node's membership and workload state automatically. To recover, rebuild or rejoin the machine using your swarm's join procedure, then verify it with docker node ls.
Done means
- Context confirmed. You checked the Docker context, CLI version and manager connection.
- Target identified. You used
docker node ls,inspectand, where relevant,psto identify the real target. - Maintenance closed out. Maintenance nodes are
Drain, service tasks have been checked, and completed nodes are restored toActive. - Membership checked. Labels, promotions and demotions were checked against placement and manager-quorum needs.
- Removal was deliberate. It was reserved for a settled node, with a rejoin plan recorded before any force action.