From e247677433eac66959ade307a68a0f5bcce58e7f Mon Sep 17 00:00:00 2001 From: Danny Groenewegen Date: Sun, 14 Jun 2026 21:04:21 +0200 Subject: [PATCH] feat: scrape metrics from containers via Docker label discovery Containers opt in with prometheus.io/scrape=true and optionally set prometheus.io/port, prometheus.io/path, and prometheus.io/auth=basic. --- config.alloy.tmpl | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/config.alloy.tmpl b/config.alloy.tmpl index 3def201..d050502 100644 --- a/config.alloy.tmpl +++ b/config.alloy.tmpl @@ -55,6 +55,90 @@ prometheus.remote_write "prometheus" { } } } + +// Scrape Prometheus metrics from other containers on this host. +// Containers opt in via Docker labels: +// prometheus.io/scrape=true required: enable scraping +// prometheus.io/port=9090 optional: port exposing /metrics (defaults to first exposed port) +// prometheus.io/path=/metrics optional: path to metrics endpoint (default: /metrics) +// prometheus.io/auth=basic optional: use basic auth with the shared basic_auth secret +// +// Uses docker_gwbridge — the host-local bridge network Docker attaches all +// Swarm containers to for outbound connectivity. Alloy can reach any container +// on the same host via this network without needing to join each stack's +// overlay network. +discovery.docker "containers" { + host = "unix:///var/run/docker.sock" + match_first_network = false +} + +discovery.relabel "metrics" { + targets = discovery.docker.containers.targets + + rule { + source_labels = ["__meta_docker_network_name"] + regex = "docker_gwbridge" + action = "keep" + } + + rule { + source_labels = ["__meta_docker_container_label_prometheus_io_scrape"] + regex = "true" + action = "keep" + } + + rule { + source_labels = ["__address__", "__meta_docker_container_label_prometheus_io_port"] + regex = `(.+):\d+;(\d+)` + target_label = "__address__" + replacement = "$1:$2" + } + + rule { + source_labels = ["__meta_docker_container_label_prometheus_io_path"] + regex = `(.+)` + target_label = "__metrics_path__" + } + + rule { + source_labels = ["__meta_docker_container_label_com_docker_swarm_service_name"] + target_label = "job" + } +} + +discovery.relabel "metrics_noauth" { + targets = discovery.relabel.metrics.output + rule { + source_labels = ["__meta_docker_container_label_prometheus_io_auth"] + regex = "^$" + action = "keep" + } +} + +discovery.relabel "metrics_basicauth" { + targets = discovery.relabel.metrics.output + rule { + source_labels = ["__meta_docker_container_label_prometheus_io_auth"] + regex = "basic" + action = "keep" + } +} + +prometheus.scrape "containers" { + scrape_interval = "120s" + targets = discovery.relabel.metrics_noauth.output + forward_to = [prometheus.remote_write.prometheus.receiver] +} + +prometheus.scrape "containers_basicauth" { + scrape_interval = "120s" + targets = discovery.relabel.metrics_basicauth.output + forward_to = [prometheus.remote_write.prometheus.receiver] + basic_auth { + username = "admin" + password = "{{ secret "basic_auth" }}" + } +} {{ end }} {{ if ne (env "LOKI_PUSH_URL") "" }}