heckenmann/docker-swarm-dashboard
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.
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
Originaldocker-swarm-dashboard
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

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:
- Open the MCP/server configuration in the agent or client.
- Add a remote MCP server.
- Select Streamable HTTP.
- Use
docker-swarm-dashboardas the server name. - Paste the MCP URL displayed by the dashboard.
- 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
codecrafters-io/build-your-own-x
Master programming by recreating your favorite technologies from scratch.
561,576 starspublic-apis/public-apis
A collective list of free APIs
497,894 starsmorluto/rea
Reverse engineer anything with agents, from app behavior down to native binaries.
449,513 starsopenclaw/openclaw
The AI that really does things. Any OS. Any Platform. The lobster way. 🦞
394,300 stars