List Docker Swarm Stacks and Read the Output Safely
You will finish with a read-only way to list the stacks known to a Docker Swarm manager, select useful output fields, and tell a connection problem from an empty result. The examples target Docker Community Edition CLI 29.8.1, installed here as package docker-ce-cli version 5:29.8.1-1~ubuntu.24.04~noble. Allow about ten minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need the Docker CLI and access to a Docker endpoint that is a Swarm manager. No command in this guide creates a Swarm, deploys a stack, removes a stack or changes a service. The command is an ordinary read-only inspection, so do not add sudo unless your Docker installation specifically requires elevated access to its socket.
1. Check the local command
Start with the installed help text. This confirms the syntax without contacting the cluster:
$ docker version --format '{{.Client.Version}}'
29.8.1
$ docker stack ls --help
Usage: docker stack ls [OPTIONS]
List stacks
The command is docker stack ls. Docker also documents docker stack list as an alias, but using ls keeps the example aligned with the installed manpage. The only option in this CLI's manpage is --format.
Checkpoint
If the help command fails, fix the CLI installation or your shell path before investigating Swarm. A working help command does not prove that the selected Docker endpoint is reachable.
2. Confirm the endpoint and manager role
List Docker contexts before asking for stacks. This is still read-only and helps prevent querying the wrong environment:
$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
Your columns may include additional information. The asterisk marks the active context. If the intended cluster is another context, select its exact name with docker context use CONTEXT_NAME, then repeat the check. That changes the CLI's local context selection, not the Swarm or its workloads, but it can send later commands to a different environment. Treat a production context as a deliberate choice.
docker stack ls is a Swarm cluster-management command and must run against a manager node. A worker endpoint cannot provide the manager API needed for this listing. Do not run docker swarm init just to make the error disappear: initialising a new Swarm changes cluster state and is outside this inspection task.
3. Print the default stack table
On a reachable manager, run:
$ docker stack ls
NAME SERVICES ORCHESTRATOR
web 3 Swarm
monitoring 2 Swarm
The names and counts are examples. The default table has column headings. It shows each stack name, the number of services, and the orchestrator reported by Docker. A manager with no stacks returns the table headings and no data rows. That is different from a connection or role error.
The command does not list individual tasks or container processes. Use the stack name with a separate inspection command when you need services or tasks, such as docker stack services STACK_NAME or docker stack ps STACK_NAME. Those commands are also read-only, but they answer a narrower question.
4. Reduce the table to stable fields
Use a Go template when a human-readable report needs only selected values. This example prints one stack per line as name: service-count:
$ docker stack ls --format '{{.Name}}: {{.Services}}'
web: 3
monitoring: 2
The documented placeholders are .Name, .Services, .Orchestrator and .Namespace. A plain template has no headings, so add your own label outside the command if a person will read the result:
$ printf '%s\n' 'STACK: SERVICES'
STACK: SERVICES
$ docker stack ls --format '{{.Name}}: {{.Services}}'
web: 3
monitoring: 2
Keep the template quoted. Single quotes prevent the shell from interpreting the braces or expanding characters before Docker receives them. If you need different formatting, change the template only; do not parse the default table by column position in a script.
5. Request JSON for scripts
The CLI supports the special json format for machine-readable records:
$ docker stack ls --format json
{"Name":"web","Namespace":"","Orchestrator":"Swarm","Services":"3"}
{"Name":"monitoring","Namespace":"","Orchestrator":"Swarm","Services":"2"}
Expect one JSON object per stack rather than assuming that the whole command is one JSON array. In a script, process each line as a JSON object and handle an empty stream as an empty stack set. Field values are emitted as strings in the documented example, including the service count. Check the actual output from your Docker version before applying numeric comparisons.
For a quick shell check that does not alter Docker state, save the output to a new temporary file rather than overwriting an existing report:
$ report_file="$(mktemp)"
$ docker stack ls --format json > "$report_file"
$ wc -l < "$report_file"
2
$ rm -- "$report_file"
The final rm deletes only the temporary report created by mktemp. It is optional and irreversible for that file, so inspect or copy the report first if it contains information you need. Do not redirect output to a known report path with > until you have decided whether replacing that file is safe.
6. Diagnose a failed listing
On a worker, or when the endpoint is not in Swarm mode, the command reports an error similar to:
$ docker stack ls
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect to swarm and try again.
The exact wording can vary. The useful diagnosis is that this endpoint is not a manager. First check docker context ls, the active DOCKER_HOST, and which machine the endpoint represents. If it is meant to be a worker, connect to a manager context instead. If the cluster is intentionally not a Swarm, use the command family for the orchestrator you actually operate.
A missing or stopped Docker daemon produces a different connection error. A permission error usually concerns access to the Docker socket. Resolve those conditions with your normal Docker administration process. Do not respond to a read-only listing failure by initialising a new cluster, joining an unknown cluster, or changing socket permissions without confirming the intended environment and obtaining the appropriate operational approval.
7. Verify the result you will use
Choose the smallest verification that matches your purpose:
- For a person checking what exists, run the default table and confirm the manager's expected stack names.
- For a short report, run the custom template and confirm that every line has the expected delimiter.
- For automation, run the JSON form and parse each non-empty line, checking that the fields your script needs are present.
Do not treat a successful exit status as proof that a stack is healthy. Listing proves that the manager returned stack metadata. It does not inspect replica readiness, task errors, image freshness, logs or application behaviour. Follow up with the relevant read-only stack, service or task inspection when those details matter.
Done means
- You checked the installed Docker CLI version and help syntax.
- You confirmed the active context points at the intended Docker endpoint.
- You ran
docker stack lsagainst a Swarm manager, or recorded the manager-role error without changing cluster state. - You can choose the default table, a field template, or line-oriented JSON output.
- You know that an empty table is not the same as a failed manager connection.
- You have not initialised, joined, deployed, removed or reconfigured a Swarm.