Skip to content
Projects

heckenmann/docker-swarm-dashboard

View on GitHub

heckenmann/docker-swarm-dashboard has 49 GitHub stars and 9 forks. GitHot measured 0 in 7 days. Last checked 2026-11-09 11:53 UTC. Last push 2026-11-04.

How these counts are measured

Dashboard for Docker Swarm Cluster

Measured star growth

in 24h
Update delayed
in 7 days
0
in 15 days
Update delayed
in 1 month
Update delayed

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

README.md

Original

GitHub release Docker CodeQL Cypress Frontend CI Server Go CI API Build & Healthcheck Lint server-src

docker-swarm-dashboard

Docker Swarm Dashboard logo

Dashboard for Docker Swarm Cluster

Docker-Image Size: < 25 MB

Use a stable release in production, not the master-build! Don't expose this service to the world! The endpoints offer the configuration of your services.

If you like this project, please give a ⭐ on github. Feedback would be nice.

Frameworks & Libraries

Screenshots

Dashboard - Light Mode Dashboard - Dark Mode Timeline Stacks Nodes Tasks Ports Logs

Getting started

Tags

Tag Description Image
e.g. 1.4.1 Stable release ghcr.io/heckenmann/docker-swarm-dashboard:1.4.1
latest Latest stable release ghcr.io/heckenmann/docker-swarm-dashboard:latest
master Current unstable master-build (not well tested) ghcr.io/heckenmann/docker-swarm-dashboard:master

Configuration

Docker Swarm Dashboard supports environment variables for configuration.

Environment variable Description Default
DSD_HTTP_PORT HTTP port within the container. Usually does not need to be changed. 8080
DSD_HANDLE_LOGS Set to false to prevent fetching and displaying logs. true
DSD_LOG_BUFFER_SIZE Maximum number of log lines buffered while streaming to a slow WebSocket client. Must be a positive integer. 64
DSD_MCP_ENABLED Enable the built-in Model Context Protocol (MCP) server and MCP connection page. true
DSD_DASHBOARD_LAYOUT Default dashboard layout. Either row (default) or column. row
DSD_HIDE_SERVICE_STATES Comma-separated list of states to not show in the main dashboard. (none)
DSD_PATH_PREFIX Set a URL path prefix for the dashboard (e.g. /dashboard). Useful when running behind a reverse proxy or when the app should not be served from the root path. /
DSD_ALLOWED_ORIGINS Comma-separated list of allowed HTTP CORS and WebSocket origins (e.g. https://dashboard.example.com). The default keeps the historical behavior and allows all origins. Set a concrete allow-list to restrict browser access. *
DSD_MASK_ENV Masks the secrets of the container specs served by the services, tasks and nodes endpoints: environment variable values, labels, credential specs, and the secrets carried by the command line and by the health check. Variable names, flags and the values of the flags that do not look like secret holders stay visible, so --log-level=debug remains readable; a secret is replaced by a fixed-length placeholder. Set to false to expose the raw values. true
DSD_NODE_EXPORTER_LABEL Docker service label to identify node-exporter service for metrics collection. dsd.node-exporter
DSD_CADVISOR_LABEL Docker service label to identify cAdvisor service for container memory metrics. dsd.cadvisor
DSD_METRICS_TIMEOUT Exporter HTTP request timeout: positive seconds or a Go duration such as 500ms or 10s. Invalid values fall back to the default. 5s
DSD_NODE_EXPORTER_PATH / DSD_CADVISOR_PATH Exporter metrics path, including an optional query string. /metrics
DSD_NODE_EXPORTER_PORT / DSD_CADVISOR_PORT Explicit internal exporter port (1–65535), overriding service port discovery. Auto-detected; fallback 9100 / 8080
DSD_NODE_EXPORTER_SCHEME / DSD_CADVISOR_SCHEME Exporter URL scheme: http or https. http
DSD_NODE_EXPORTER_HEADERS / DSD_CADVISOR_HEADERS JSON object of additional HTTP headers for exporter requests, including optional Host. None
LOCALE Timestamp format based on a BCP 47 language tag. (system)
TZ IANA Time zone to display timestamps in. (system)
DSD_VERSION_CHECK_ENABLED When true, the system will check for updates and notify in the UI if a new version is available. false
DSD_VERSION_CHECK_CACHE_TIMEOUT_MINUTES Cache duration in minutes for version check results. 60
DSD_WELCOME_MESSAGE If set, this message will be displayed to the user in a modal dialog when the web application is opened in the browser. (none)
DOCKER_API_VERSION Forces a specific Docker API version to use (e.g. 1.35, 1.41). When not specified, the server automatically negotiates the highest API version supported by both the client and Docker daemon. Only set this if you need to force a specific version for compatibility. (auto-negotiated)

If DSD_ALLOWED_ORIGINS is not set, the server logs a startup warning because all HTTP CORS and WebSocket origins are allowed for backward compatibility.

UI Default Settings

These environment variables control the default UI state. All settings can be changed by the user in the web interface and are persisted in the URL hash.

Environment variable Description Default
DSD_TABLE_SIZE Default table size. Either sm (small) or lg (large). sm
DSD_SERVICE_NAME_FILTER Default service name filter value. (none)
DSD_STACK_NAME_FILTER Default stack name filter value. (none)
DSD_FILTER_TYPE Default filter type. Either service or stack. service
DSD_LOGS_NUMBER_OF_LINES Default number of log lines to fetch. 100
DSD_LOGS_MESSAGE_MAX_LEN Maximum length of log messages to display. 2000
DSD_LOGS_FORM_TAIL Default line count or all for the logs form and omitted MCP log tails. 20
DSD_LOGS_FORM_SINCE Default value for since option in logs form. false
DSD_LOGS_FORM_SINCE_AMOUNT Default amount for since option in logs form. 15
DSD_LOGS_FORM_SINCE_UNIT Default unit for since option in logs form. Either minutes, hours, or days. minutes
DSD_LOGS_FORM_FOLLOW Default value for follow option in logs form. false
DSD_LOGS_FORM_TIMESTAMPS Default value for timestamps option in logs form. true
DSD_LOGS_FORM_STDOUT Default value for stdout option in logs form. true
DSD_LOGS_FORM_STDERR Default value for stderr option in logs form. true
DSD_LOGS_FORM_DETAILS Default value for details option in logs form. true
DSD_LOGS_SEARCH_KEYWORD Default search keyword for logs. (none)
DSD_DARK_MODE Enable dark mode by default. Either true or false. false
DSD_SHOW_NAMES_BUTTONS Show action buttons in entity names by default. Either true or false. true
DSD_SHOW_NAV_LABELS Show navigation labels by default. Either true or false. false
DSD_MAX_CONTENT_WIDTH Maximum content width. Either fluid (full width) or fixed (container width). fluid

Swarm control-plane observations

The Nodes page groups control-plane status and cluster-wide resources in a shared Cluster Overview. It shows manager reachability, the reported leader, the majority required for quorum, and an estimated reserve for additional manager failures. Warnings identify single or even manager sets, unreachable or unknown managers, and missing leaders or insufficient observed reachable managers. Warning links open the affected nodes. The inventory includes each node's advertised Docker Engine version, OS, architecture, and scheduling availability.

This uses Docker node information and works without node-exporter. Reachability is separate from scheduling availability: a drained manager may still participate in consensus. Docker-reported observations are not an independent Raft probe; existing workloads may continue while cluster administration is unavailable.

GET /docker/cluster/health and MCP get_cluster_health share the same read-only assessment. Responses include available, state, observedAt (UTC), manager counts, majority, remainingFailures, leaderIds, structured warnings, and a node inventory. Unknown reachability or a missing/ambiguous leader makes the reserve unknown (null). Counts refer to managers configured in the returned node list, not an independently verified Raft membership list.

Docker node queries for this assessment have a five-second deadline. On failure, REST returns HTTP 503 and MCP returns available: false, state: "unavailable", with no successful observation timestamp or reserve. Old successful observations are never substituted for failed queries. Refresh uses the dashboard's existing refresh controls. The existing /health endpoint retains its Docker connectivity check.

Model Context Protocol (MCP)

Docker Swarm Dashboard includes a built-in, read-only MCP server so MCP-capable agents can inspect the same cluster information that is available through the web UI. MCP is enabled by default and can be disabled with DSD_MCP_ENABLED=false.

The server uses Streamable HTTP. Its endpoint is /mcp and follows DSD_PATH_PREFIX:

https://dashboard.example.com/mcp
https://dashboard.example.com/docker-dashboard/mcp

When MCP is enabled, the dashboard shows an MCP navigation entry. The MCP page displays the endpoint for the current deployment and provides generic connection instructions for MCP-capable agents.

To connect an agent:

  1. Open the MCP/server configuration in the agent or client.
  2. Add a remote MCP server.
  3. Select Streamable HTTP.
  4. Use docker-swarm-dashboard as the server name.
  5. Paste the MCP URL displayed by the dashboard.
  6. Connect and let the client discover the available tools.

The MCP server exposes read-only information for services, nodes, tasks, metrics, logs (when DSD_HANDLE_LOGS=true), stacks, published ports, the timeline, dashboard settings, version, and health. Existing DSD_MASK_ENV masking is also applied to data returned through MCP.

Tools include list_services, get_service, get_service_metrics, list_nodes, get_node, get_node_metrics, get_cluster_metrics, get_cluster_health, list_tasks, get_task, get_task_metrics, list_stacks, list_published_ports, get_timeline, get_cluster_overview, get_dashboard_settings, get_version, and get_health. When logs are enabled, list_log_services and get_service_logs are also discoverable. Service queries accept IDs or exact names, node queries accept IDs, node names or hostnames, and task queries accept IDs. list_tasks accepts optional service and node filters.

Results contain structured JSON objects, with named fields such as services, nodes, tasks, stacks, ports, and timeline for lists, plus a text fallback for clients using older MCP protocol versions. The cluster overview contains services, nodes and tasks independently of the dashboard layout. Log queries return finite snapshots, support the dashboard's Docker log options, and stop with an error if Docker does not finish within five seconds. An omitted tail uses logsFormTail from dashboard settings, falling back to 20; an omitted since applies no time filter. Boolean log options use the configured dashboard defaults. Tool discovery describes these defaults. Metrics results expose availability and diagnostic messages when exporters are missing or fail. Check available, message, and error before using metric values, including when available is true. Exporter HTTP requests have a five-second timeout, and Docker/exporter work honors request cancellation. The connection URL uses the server's configured path prefix and the current browser origin; a client-side API URL override does not change it.

Log retrieval

The WebSocket log viewer decodes Docker multiplex frames before splitting text into lines and preserves raw output for TTY services. Non-follow requests wait for a complete snapshot instead of treating a pause in output as completion. A snapshot that does not finish within 20 seconds, or contains an incomplete Docker frame, closes with an error. MCP log requests use the five-second limit described above. For the WebSocket viewer, omitted tail or tail=all returns all available history, tail=0 returns no historical lines, and a positive number selects the last N lines. Invalid values fall back to 20, consistently for the Docker request and the returned snapshot.

For finite snapshots, Docker Swarm returns at most the requested number of lines from each task's log history. The dashboard orders these candidates by Docker timestamps and then applies the requested tail across the service. This keeps normal tail requests bounded to the requested count per task instead of reading each task's full history. The returned lines are oldest-to-newest, and valid timestamps are fetched internally even when their display is disabled. Lines with missing or malformed timestamps are retained in their original order before timestamped lines. Equal timestamps retain Docker's arrival order. This ordering uses timestamps supplied by each node, so clock skew can affect the apparent chronology. An explicit tail=all still reads all available history.

Follow mode keeps Docker's arrival order and does not wait for delayed task logs. Its reader uses a bounded queue, avoiding unbounded buffering at the cost of not reordering late entries in a live stream.

Pull Image from ghcr.io

docker pull ghcr.io/heckenmann/docker-swarm-dashboard:master

docker-compose.yml

---
version: '3.5'

services:
  docker-swarm-dashboard:
    image: ghcr.io/heckenmann/docker-swarm-dashboard:master
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
    ports:
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    environment:
      DSD_MCP_ENABLED: 'true'

docker-compose.yml with traefik and basic auth

This configuration sets a password for access. It is importand to configure ssl in traefik for better security.

In this example you can login with "docker / docker" on port 8080.

Have a look at https://doc.traefik.io/traefik/user-guides/docker-compose/acme-tls/

---
version: '3.5'

services:
  docker-swarm-dashboard:
    image: ghcr.io/heckenmann/docker-swarm-dashboard:master
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.dsd.entrypoints=web"
        - "traefik.http.routers.dsd.middlewares=basic-auth"
        - "traefik.http.services.dsd.loadbalancer.server.port=8080"
        - "traefik.http.routers.dsd.rule=PathPrefix(`/`)"
        # Login with docker / docker
        - "traefik.http.middlewares.basic-auth.basicauth.users=docker:$$2y$$10$$81nFbUw842iBd7MlngMR4.1VBI9j6Y.vTiamBAqtVNfs4qehzZB.e"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"

  traefik:
    image: "traefik:v2.9"
    deploy:
      placement:
        constraints:
          - node.role == manager
    command:
      #- "--log.level=debug"
      #- "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.swarmMode=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:8080"
    ports:
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

Deploy on docker-swarm

From the directory with docker-compose.yml run:

docker stack deploy --compose-file docker-compose.yml docker-swarm-dashboard

Metrics Integration (Optional)

Docker Swarm Dashboard supports optional integration with Prometheus Node Exporter and cAdvisor for enhanced metrics visualization.

Overview

Metric Source Provides Discovery Label Default Label
Node Exporter Node-level metrics (CPU, memory, disk, network) dsd.node-exporter dsd.node-exporter=true
cAdvisor Container-level metrics (memory usage per container) dsd.cadvisor dsd.cadvisor=true

Both services should be deployed as global services on the same overlay network as the dashboard.

Exporter endpoint settings use this priority: service labels, dashboard environment variables, then the existing discovery defaults. Set labels under deploy.labels on the exporter service, for example:

deploy:
  labels:
    dsd.node-exporter: "true"
    dsd.node-exporter.path: "/prometheus/metrics"
    dsd.node-exporter.port: "19100"
    dsd.node-exporter.scheme: "https"

For cAdvisor, use dsd.cadvisor.path, dsd.cadvisor.port, and dsd.cadvisor.scheme. These configuration labels remain fixed even if the discovery label is customized. Ports refer to the exporter listener reachable inside the overlay network. Discovery still selects the task on the requested node and prefers a network shared with the dashboard.

Paths must start with a single /; fragments and absolute URLs are rejected. Invalid endpoint settings make the affected metrics unavailable with a diagnostic error. HTTPS uses the system certificate trust store. Reverse proxies can receive custom headers through the dashboard environment, for example DSD_NODE_EXPORTER_HEADERS='{"Host":"metrics.internal","X-Tenant":"operations"}'. Malformed header JSON fails the request without logging its contents. Keep credentials out of service labels.

DSD_METRICS_TIMEOUT is read when the dashboard starts and limits each exporter HTTP request, including its response body. Earlier request cancellation still takes precedence. These settings apply to node, cluster, service, and task metrics in both the dashboard and MCP tools.


Node Exporter Setup

Purpose: Displays node-level system metrics (CPU, memory, disk, network usage per swarm node).

Deployment:

node-exporter:
  image: prom/node-exporter:latest
  deploy:
    mode: global
    placement:
      constraints:
        - node.role == manager   # Or remove for all nodes
    labels:
      - "dsd.node-exporter=true"
  networks:
    - your-network-name
  volumes:
    - /proc:/host/proc:ro
    - /sys:/host/sys:ro
    - /:/rootfs:ro
  command:
    - '--path.procfs=/host/proc'
    - '--path.sysfs=/host/sys'
    - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'

Customize Discovery Label:

environment:
  DSD_NODE_EXPORTER_LABEL: "my.custom.label"

cAdvisor Setup

Purpose: Displays container-level memory metrics per service (memory usage, limits, per-container breakdown).

Deployment:

cadvisor:
  image: gcr.io/cadvisor/cadvisor:latest
  deploy:
    mode: global
    placement:
      constraints:
        - node.role == manager   # Or remove for all nodes
    labels:
      - "dsd.cadvisor=true"
  networks:
    - your-network-name
  volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:ro
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro
    - /dev/disk/:/dev/disk:ro
  command:
    - '--docker_only=true'
    - '--housekeeping_interval=30s'

Customize Discovery Label:

environment:
  DSD_CADVISOR_LABEL: "my.custom.label"

Metrics Displayed

Node Exporter Metrics:

  • CPU usage per node
  • Memory usage per node
  • Disk I/O and storage
  • Network traffic per node

cAdvisor Metrics (Service Metrics Tab):

  • Total Memory Usage: Aggregate memory usage across all containers in the service
  • Memory Limits: Configured memory limits for each container
  • Per-Container Breakdown: Memory usage for each task/container in the service
  • Usage Percentage: Memory usage as a percentage of the configured limit

Benefits of cAdvisor:

  • Identify memory-hungry containers within a service
  • Monitor services approaching memory limits
  • Detect potential out-of-memory (OOM) situations before they occur

Network Configuration

Both services should be attached to the same overlay network as the dashboard for container-to-container communication:

networks:
  - your-network-name  # Same network as docker-swarm-dashboard

This ensures metrics are only reachable from within the overlay network (recommended for security).

logs-generator (for testing)

docker service create --name logger chentex/random-logger:latest 50 200

Development

Local Build

docker build -t ghcr.io/heckenmann/docker-swarm-dashboard:local .

Run api-mock-server

# from app-src
yarn run start-api-mock

Run UI

# from app-src
yarn run start-dev-server

When you run the UI with the api-mock-server, you have to open the ui with "base"-param (API-URL): http://localhost:3000#base="http%3A%2F%2Flocalhost%3A3001%2F"

Run UI-tests

# from app-src
yarn run cy:run

Explore related projects