A runnable monitoring lab: a Python service exposes Prometheus metrics, Prometheus scrapes it, and Grafana displays a provisioned dashboard.
docker compose up --buildOpen the application at http://localhost:8000, Prometheus at http://localhost:9090, and Grafana at http://localhost:3000. The dashboard and data source are provisioned automatically.
- metrics endpoint and scrape configuration;
- Docker Compose service dependencies and read-only configuration mounts;
- Grafana dashboard as code;
- Kubernetes Deployment, Service and Prometheus Operator ServiceMonitor;
- CI checks tests, JSON configuration and image build.
Replace OWNER in k8s/app.yaml before pushing the image. The ServiceMonitor requires the Prometheus Operator or kube-prometheus-stack.
App (/metrics) -> Prometheus (scrape) -> Grafana (provisioned dashboard)
-> Prometheus Operator ServiceMonitor (k8s)
app/main.py— exposesapp_uptime_secondsand serves the app.prometheus/prometheus.yml— scrape config;grafana/provisioning/*— dashboard and data source as code.compose.yaml— service dependencies and read-only config mounts.
"Dashboards as code" means the Grafana provisioning YAML is version controlled and reviewed like everything else, so a broken dashboard is a merge conflict, not a manual click. Sharing the metrics port across the Compose stack and giving Prometheus a service dependency ordering keeps the scrape loop stable during startup, and the same manifest works unchanged for the k8s ServiceMonitor.
| Service | Port | Use |
|---|---|---|
| App | 8000 | http://localhost:8000 |
| Prometheus | 9090 | metrics browser |
| Grafana | 3000 | dashboards |
| (Prod) ServiceMonitor | cluster-IP | cluster scraping |