How to List All Containers Across Docker Swarm Nodes: CLI & API Solutions


1 views

When managing a Docker Swarm cluster, administrators often need comprehensive visibility into container distribution across nodes. The default docker ps command only shows containers running on the current node, which creates operational blind spots in a multi-node environment.

While Docker doesn't provide a single command for swarm-wide container listing, we can combine several approaches:

# Method 1: Query each node via SSH (requires SSH access)
for node in $(docker node ls -q); do
  echo "Containers on node $(docker node inspect --format '{{ .Description.Hostname }}' $node):"
  ssh $(docker node inspect --format '{{ .Description.Hostname }}' $node) \
    "docker ps -a --format 'table {{.ID}}\\t{{.Image}}\\t{{.Status}}\\t{{.Names}}'"
done

For service-based containers, we can extract container information through service inspection:

# Method 2: Service-based container discovery
docker service ls -q | xargs -I{} docker service ps {} \
  --format '{{.Name}}.{{.ID}}\t{{.Node}}\t{{.CurrentState}}\t{{.Image}}'

For more detailed information, the Docker API provides comprehensive data:

# Method 3: Using Docker API (Python example)
import docker

client = docker.DockerClient(base_url='unix://var/run/docker.sock')
nodes = client.nodes.list()

for node in nodes:
    node_client = docker.DockerClient(base_url=f"tcp://{node.attrs['Status']['Addr']}:2376")
    print(f"Node: {node.attrs['Description']['Hostname']}")
    for container in node_client.containers.list(all=True):
        print(f"  {container.id[:12]} {container.status} {container.name}")

Several open-source solutions can help visualize swarm container distribution:

  • Portainer: Provides a web UI for container management
  • Swarmpit: Lightweight Docker Swarm management UI
  • cAdvisor: Container monitoring tool with swarm support

When implementing swarm-wide container listing, remember:

  • API requests may impact swarm performance during heavy loads
  • SSH-based methods require proper key distribution
  • TLS should be properly configured for secure API communication
  • Consider implementing caching for frequent queries

When working with Docker Swarm mode, one common frustration is the lack of a straightforward command to view all containers across all swarm nodes. While docker service ls shows services and docker node ls displays nodes, there's no direct command to see individual containers with their statuses.

Here are several approaches to get container information across your swarm:

# Method 1: Using docker service ps with --format
docker service ps --format "table {{.Name}}\t{{.Node}}\t{{.CurrentState}}\t{{.Image}}" $(docker service ls -q)

# Method 2: Combining docker node ls with SSH
for node in $(docker node ls --format "{{.Hostname}}"); do
  echo "=== Containers on $node ==="
  ssh $node docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}"
done

For more detailed information, you can query the Docker API directly:

# Get all services
curl -s --unix-socket /var/run/docker.sock http://localhost/services | jq .

# Get tasks for all services
SERVICES=$(curl -s --unix-socket /var/run/docker.sock http://localhost/services | jq -r '.[].ID')
for service in $SERVICES; do
  curl -s --unix-socket /var/run/docker.sock http://localhost/services/$service/tasks | jq .
done

Consider these tools for better swarm container management:

# Portainer (web UI)
docker service create \
  --name portainer \
  --publish 9000:9000 \
  --mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
  portainer/portainer

# Swarmpit (lightweight alternative)
docker stack deploy -c https://swarmpit.io/install/stack.yml swarmpit

Here's a Python script using Docker SDK to gather container info:

import docker

client = docker.from_env()
nodes = client.nodes.list()

for node in nodes:
    node.reload()
    print(f"Node: {node.attrs['Description']['Hostname']}")
    for container in node.attrs.get('Status', {}).get('Containers', []):
        print(f"  Container: {container.get('Names', ['unnamed'])[0]}")
        print(f"    Status: {container.get('State', 'unknown')}")
        print(f"    Image: {container.get('Image', 'unknown')}\n")