If you’re running Portainer to manage your homelab containers, you’re probably also wondering what those containers are actually doing. CPU spikes, memory leaks, network hiccups—Portainer’s built-in graphs give you a surface-level view, but they’re not enough for real troubleshooting. That’s where integrating Portainer with Prometheus comes in. You can pull detailed container metrics directly into Portainer’s dashboard without leaving the UI, assuming you already have Prometheus scraping Docker stats somewhere.

Why Integrate Portainer with Prometheus at All
Portainer shows you what’s running. Prometheus tells you how hard it’s running. By itself, Portainer gives you a containers list, lets you restart things, and shows memory usage in a box graph that updates every few seconds. You can see that nginx is using 45MB, but you can’t see if it was 20MB five minutes ago or if it’s trending upward. You can’t set alerts. You can’t correlate a spike with something else happening on your network.
Prometheus, running separately, scrapes metrics from cAdvisor (which sits on your Docker host) every 15 seconds by default, stores them with timestamps, and keeps history. When you wire Portainer’s custom metrics support into Prometheus, you get a hybrid view: Portainer’s container management interface with Prometheus’s time-series data backing it up. That sounds better than it actually is in practice, which I’ll get to.
The real value is consolidation. Instead of flipping between three tabs (Portainer for logs, Grafana for graphs, Prometheus for raw queries), you can stay in Portainer and see the trend. For a homelab with five to twenty containers, that’s nice. For fifty containers running across three nodes, Portainer alone becomes a clicking nightmare and Prometheus becomes mandatory anyway. The integration doesn’t replace either tool; it just borrows from one to improve the other.
Prerequisites: What You Need Before Starting
You need a working Portainer instance—Community Edition is fine for up to three Docker nodes. You also need Prometheus already running and scraping container metrics. If you’re using cAdvisor for Docker stats, Prometheus should already have a scrape job pointing at your Docker host or cAdvisor container.
Check that Prometheus is actually collecting Docker metrics. Open your Prometheus web UI and search for a metric like container_memory_usage_bytes or container_cpu_usage_seconds_total. If you see results, you’re good. If not, your Prometheus isn’t configured to scrape those yet. That’s a separate setup. This article assumes you’ve already done that part.
You’ll need network connectivity between your Portainer container and your Prometheus container. If they’re on the same Docker network, that’s automatic. If Prometheus is on a different host or behind a firewall, you’ll need to sort that out. And you need Portainer version 2.13 or later for custom metrics to work reliably. Check your version in the top-left corner of the Portainer UI.
Configuring Prometheus for Portainer Scraping
Your Prometheus needs to scrape two targets: the Docker metrics themselves (usually cAdvisor on port 8080 or via the Docker daemon on 9323) and optionally the node exporter for host-level stats. I’m assuming you’ve got the Docker metrics part working. If not, add this to your prometheus.yml:
scrape_configs:
- job_name: 'docker'
static_configs:
- targets: ['localhost:9323']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
Replace localhost:9323 with your actual Docker metrics endpoint if it’s different, and replace cadvisor:8080 with the hostname or IP of your cAdvisor container. Reload Prometheus after editing (either restart the container or hit the config reload endpoint if you’ve enabled it).
The trick here is that Portainer doesn’t directly scrape Prometheus for metrics. Instead, Portainer exposes a metrics endpoint that *Prometheus* scrapes, and Portainer pulls those metrics from Prometheus when you ask for them in the UI. It’s backwards from what you’d expect. You’re not telling Portainer “go ask Prometheus for data.” You’re telling Portainer “here’s where Prometheus lives, and I’ll query it on your behalf.”
Adding Prometheus as a Custom Metrics Source in Portainer
Open Portainer, click Settings in the bottom-left (or under your username menu, depending on your version). Look for Custom Metrics or Environment Management. Newer versions put this under Environments if you have multiple Docker hosts registered.
You want to add Prometheus as a metrics provider. Click the button to add a new metrics source. You’ll see options for Prometheus. Enter:
- Prometheus URL:
http://prometheus:9090(or whatever your Prometheus hostname and port are. If it’s on a different machine, use the full IP or DNS name.) - Name: Something like “Prometheus – Main” or just “Prometheus”
- Query timeout: Leave this at the default (usually 30 seconds) unless you know your Prometheus is slow.
Test the connection. If it fails, check that Prometheus is actually running, that the hostname resolves, and that there’s no firewall blocking port 9090 between Portainer and Prometheus. I spent an embarrassing thirty minutes once debugging this only to realize my Prometheus container had crashed and nobody told me.
Save it. Now Portainer knows where Prometheus is. But it still doesn’t know which metrics to pull or how to display them.
Creating Custom Dashboards and Metric Queries
This is where things get clunky. Portainer doesn’t auto-magically show you metrics from Prometheus. You have to manually configure which metrics you want to see and how to query them.
Go to a container or stack detail page. At the top, look for a Stats or Metrics tab. Click it. By default you’ll see Portainer’s built-in graphs (memory, CPU, network). Below those, there should be an option to add a custom metric or query Prometheus directly. The exact UI varies by Portainer version, which is annoying.
To add a metric, you write a PromQL query. For example, to see memory usage for a specific container, you’d write something like:
container_memory_usage_bytes{name="my-container"}
Or for CPU usage:
rate(container_cpu_usage_seconds_total{name="my-container"}[5m])
The metric names depend on what cAdvisor or your Docker metrics exporter is actually publishing. Check Prometheus’s targets and scrape results to see what’s available.
Here’s the friction: container name matching is fragile. If your container is called my-app in Docker, the metric might label it as my-app, or my-app.1 (if it’s a Swarm task), or just its container ID. You have to experiment or check raw Prometheus queries to figure out the right label. And if you rename the container, your custom metrics break silently.
For a homelab, I usually end up writing a few queries and saving them as custom dashboards in Portainer’s dashboard editor. It’s not elegant, but it works. You can create a dashboard that shows memory and CPU for your top five containers, network I/O, or whatever you care about.
A Realistic Example: Monitoring an Ollama Container
Let’s say you’re running Ollama in a container through Portainer. You want to see its memory usage and GPU utilization trend over the last hour. Here’s how you’d do it.
In Prometheus, you’d query:
container_memory_usage_bytes{name="ollama"}
If that returns nothing, try:
container_memory_usage_bytes{container_label_com_docker_compose_service="ollama"}
Once you find the right label, add it to a custom Portainer dashboard. You’ll get a graph showing memory over time, pulled live from Prometheus every time you refresh the page. You can see if Ollama memory is stable at 8GB or creeping up to 10GB over the course of a day.
For GPU metrics, it gets harder. cAdvisor and basic Docker metrics don’t expose NVIDIA GPU usage out of the box. You’d need nvidia-docker running and potentially a separate exporter. This is where Portainer’s integration starts to feel limited. You can’t see what Portainer doesn’t have a query for, and not everything exposes metrics cleanly.
Common Issues and Rough Edges
The biggest issue is latency. Portainer queries Prometheus synchronously when you load a page. If Prometheus is slow or you’re asking for a long time range, the UI freezes for a few seconds. It’s not a showstopper, but it’s not snappy like the built-in Portainer stats.
Container name mismatches will catch you. A container can have multiple labels, and the label Prometheus uses might not match what you expect. I’ve had to trial-and-error through four or five different label combinations before finding the right one.
If you stop and restart your containers, old metrics remain in Prometheus. You’ll see graphs for containers that don’t exist anymore. That’s Prometheus’s behavior, not Portainer’s fault, but it’s worth knowing.
Portainer’s custom metrics UI is not intuitive for anyone who hasn’t written PromQL queries before. If you’re new to Prometheus, you’ll spend time learning the syntax. That’s not a reason to skip it, but it’s not “add a data source and you’re done” either.
When This Actually Helps and When It Doesn’t
This integration shines if you’re already running Prometheus and you want a single pane of glass for container management and monitoring. If you’re only managing five containers and you just want to make sure they’re not dying, the built-in Portainer stats are probably enough and this adds complexity you don’t need.
If you’re running a larger homelab with services that have performance issues—Ollama model loads, database queries, backup jobs—having Prometheus metrics accessible through Portainer means you can investigate without switching tools. You can see that your n8n automation spiked CPU at 3 PM and correlate it with a webhook flood or a slow API call, all from within Portainer’s UI.
But Portainer is not Grafana. If you need sophisticated dashboards, alerts, or multi-metric correlations, you’re going to end up in Grafana anyway. Portainer’s custom metrics are a nice-to-have supplement, not a replacement. Think of it as letting you see the trend without leaving the management interface.
My honest take: this integration is worth setting up if you’re already maintaining both Portainer and Prometheus. It’s not worth introducing Prometheus into your homelab just to get metrics in Portainer. If you’re at that point, just use Grafana. It’s better at visualization anyway.
FAQ
Can Portainer pull metrics from Prometheus without cAdvisor?
Technically yes—Prometheus just needs to be scraping metrics from any exporter that exposes container-like data. But cAdvisor is the standard. If you’re using node exporter or a custom exporter, you can write PromQL queries against those metrics instead.
Do I need to restart Portainer after configuring Prometheus?
No. The connection is tested when you save it. If the test passes, Portainer can start querying immediately. No restart needed.
Why does my custom metric query return no data in Portainer?
Most likely your PromQL query is wrong or the metric doesn’t exist. Test the query directly in Prometheus’s web UI first to make sure it returns data, then copy it into Portainer. Check that your container labels match what Prometheus actually scraped.
Does Portainer Community Edition support Prometheus integration?
Yes. Custom metrics and Prometheus integration work in Community Edition. There’s no paywall for this feature.
What happens if Prometheus goes down?
Portainer’s custom metric queries will time out or fail. The built-in stats (from the local container runtime) will still work. Portainer won’t crash, but you’ll see errors on the custom metrics graphs until Prometheus comes back online.
Explore Portainer in our AI Homelab Toolkit.