|
| 1 | +## Portainer Dashboard |
| 2 | + |
| 3 | +A widget to display a dashboard of your portainer services. |
| 4 | + |
| 5 | +### Preview |
| 6 | + |
| 7 | + |
| 8 | +### Requirements |
| 9 | + |
| 10 | +#### Get the PORTAINER_API_KEY |
| 11 | +1. Open your portainer dashboard and go to `Settings` -> `API` -> `Enable API`. |
| 12 | +2. Copy the `API Key`. |
| 13 | +3. Set the `PORTAINER_API_KEY` environment variable to the API key. |
| 14 | + |
| 15 | + |
| 16 | +#### Get the PORTAINER_ENDPOINT_ID and PORTAINER_URL |
| 17 | +1. Open your portainer dashboard. |
| 18 | +2. Copy the browser URL and extract the endpoint ID from the URL. e.g. `http://<your-portainer-url>/#!/2/docker/dashboard` -> `2` |
| 19 | +3. Set the `PORTAINER_ENDPOINT_ID` environment variable to the endpoint ID. |
| 20 | +4. Set the `PORTAINER_URL` environment variable to the portainer URL. e.g. `http://<your-portainer-url>` |
| 21 | + |
| 22 | +Once the prerequisites and setup are complete, copy the code below and add it to your `glance.yml` file. |
| 23 | + |
| 24 | +```yaml |
| 25 | +- type: custom-api |
| 26 | + title: Portainer |
| 27 | + cache: 1h |
| 28 | + url: ${PORTAINER_URL}/api/endpoints/${PORTAINER_ENDPOINT_ID} |
| 29 | + headers: |
| 30 | + X-API-Key: ${PORTAINER_API_KEY} |
| 31 | + template: | |
| 32 | + <style> |
| 33 | + .list-horizontal-text.no-bullets > *:not(:last-child)::after { |
| 34 | + content: none !important; |
| 35 | + } |
| 36 | + .list-horizontal-text.no-bullets > *:not(:last-child) { |
| 37 | + margin-right: 1em; |
| 38 | + } |
| 39 | + </style> |
| 40 | + <div style="display:flex; align-items:center; gap:12px;"> |
| 41 | + <div style="width:40px; height:40px; flex-shrink:0; display:flex; justify-content:center; align-items:center; overflow:hidden;"> |
| 42 | + <img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/portainer-dark.svg" width="24" height="24" style="object-fit:contain;"> |
| 43 | + </div> |
| 44 | + <div style="flex-grow:1; min-width:0;"> |
| 45 | + <a class="size-h4 block text-truncate color-highlight"> |
| 46 | + {{ .JSON.String "Name" }} |
| 47 | + <span style="width: 8px; height: 8px; border-radius: 50%; background-color: var(--color-positive); display: inline-block; vertical-align: middle;"></span> |
| 48 | + </a> |
| 49 | + <ul class="list-horizontal-text no-bullets"> |
| 50 | + <li data-popover-type="text" data-popover-text="Containers: {{ .JSON.Int "Snapshots.0.ContainerCount" }}"> |
| 51 | + <p style="display:inline-flex;align-items:center;"> |
| 52 | + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="height:1em;vertical-align:middle;margin-right:0.5em;" class="size-6 lucide lucide-box icon inline-flex" aria-hidden="true" role="img"><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"></path><path d="m3.3 7 8.7 5 8.7-5"></path><path d="M12 22V12"></path></svg> |
| 53 | + {{ .JSON.Int "Snapshots.0.ContainerCount" }} |
| 54 | + </p> |
| 55 | + </li> |
| 56 | + <li data-popover-type="text" data-popover-text="Volumes: {{ .JSON.Int "Snapshots.0.VolumeCount" }}"> |
| 57 | + <p style="display:inline-flex;align-items:center;"> |
| 58 | + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="height:1em;vertical-align:middle;margin-right:0.5em;" class="size-6 lucide lucide-database icon inline-flex" aria-hidden="true" role="img"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M3 5V19A9 3 0 0 0 21 19V5"></path><path d="M3 12A9 3 0 0 0 21 12"></path></svg> |
| 59 | + {{ .JSON.Int "Snapshots.0.VolumeCount" }} |
| 60 | + </p> |
| 61 | + </li> |
| 62 | + <li data-popover-type="text" data-popover-text="Networks: {{ .JSON.Int "Snapshots.0.DockerSnapshotRaw.Networks.#" }}"> |
| 63 | + <p style="display:inline-flex;align-items:center;"> |
| 64 | + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="height:1em;vertical-align:middle;margin-right:0.5em;" class="size-6 lucide lucide-network icon inline-flex" aria-hidden="true" role="img"><rect x="16" y="16" width="6" height="6" rx="1"></rect><rect x="2" y="16" width="6" height="6" rx="1"></rect><rect x="9" y="2" width="6" height="6" rx="1"></rect><path d="M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"></path><path d="M12 12V8"></path></svg> |
| 65 | + {{ .JSON.Int "Snapshots.0.DockerSnapshotRaw.Networks.#" }} |
| 66 | + </p> |
| 67 | + </li> |
| 68 | + </ul> |
| 69 | + </div> |
| 70 | + </div> |
| 71 | + <div class="margin-block-2" style="margin-top: 1em"> |
| 72 | + <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> |
| 73 | + <div> |
| 74 | + <div class="size-h5">Running</div> |
| 75 | + <div class="size-h3 color-highlight">{{ .JSON.Int "Snapshots.0.RunningContainerCount" }}</div> |
| 76 | + </div> |
| 77 | + <div> |
| 78 | + <div class="size-h5">Healthy</div> |
| 79 | + <div class="size-h3 color-highlight">{{ .JSON.Int "Snapshots.0.HealthyContainerCount" }}</div> |
| 80 | + </div> |
| 81 | + <div> |
| 82 | + <div class="size-h5">Stopped</div> |
| 83 | + <div class="size-h3 color-highlight">{{ .JSON.Int "Snapshots.0.StoppedContainerCount" }}</div> |
| 84 | + </div> |
| 85 | + <div> |
| 86 | + <div class="size-h5">Unhealthy</div> |
| 87 | + <div class="size-h3 color-highlight">{{ .JSON.Int "Snapshots.0.DockerSnapshotRaw.Containers.#(Health=\"unhealthy\").#" }}</div> |
| 88 | + </div> |
| 89 | + </div> |
| 90 | + </div> |
| 91 | +``` |
0 commit comments