Serve, Prometheus and Grafana with Docker Compose¶
For the minimal agent or its optional web UI, start with the Compose quickstart.
This optional example starts the complete serve mode stack and loads the dashboard automatically. It observes real containers on your Docker daemon and executes no remediation rules. For a command that exits after one cycle, use simple mode; none of this stack is required for it.
Start¶
Use Docker Engine with Linux containers, a local Unix Docker socket, and a recent
Docker Compose v2 with up --wait support. Docker Desktop with Linux containers
can also be used, although this example is tested in CI on Linux Docker Engine.
The account running these commands must have Docker access. Git and a POSIX shell
are used below; Windows users can run the commands in WSL with Docker integration.
git clone https://github.com/decryptus/monit-docker.git
cd monit-docker/examples/monitoring
sh start.sh
The first run downloads the pinned images and generates a random Grafana admin
password in .env, with permissions 0600. Subsequent runs reuse that file.
The script waits for healthy services; startup may take several minutes. It does
not print the password. In your local terminal, read it with:
cat .env
Open http://127.0.0.1:3000, log in as admin with that password, and open the monit-docker — Overview dashboard in the monit-docker folder. It is also configured as the home dashboard. Prometheus is already connected; no JSON import or data-source setup is needed.
The dashboard shows the host’s containers, including the monitoring stack itself. Allow roughly one to two minutes for several scrapes before interpreting rate panels. The gallery illustrates the layout with synthetic data; this Compose example uses your actual measurements.
Three alert rules are loaded automatically. Open
http://127.0.0.1:9090/alerts to see agent availability, collection readiness
and high container memory alerts. See the alert guide for thresholds,
diagnosis and customization. This example sends no outbound notifications.
To opt in to email, Slack or both, use the notification guide
and sh start.sh --notifications after configuring your receivers.
What runs and where data lives¶
Service |
Local address |
Stored data |
|---|---|---|
monit-docker |
http://127.0.0.1:9808 |
Latest completed cycle in memory; cleared on restart |
Prometheus |
http://127.0.0.1:9090 |
Time-series history in the |
Grafana |
http://127.0.0.1:3000 |
Users, preferences and saved dashboards in the |
All published ports bind to host loopback. Containers communicate over their
Compose network: Prometheus scrapes monit-docker:9808, and Grafana queries
prometheus:9090. Changing a host port does not change these internal addresses.
Only the agent receives the Docker socket. Access to that socket grants control
of the Docker daemon even when the mount has read_only: true; that mount flag
does not make the Docker API read-only. The example runs no action rules.
Prometheus and Grafana add their own resource usage. They are optional external services and do not become dependencies of the lightweight agent.
Check the first measurements¶
Run from examples/monitoring:
docker compose ps
curl -i http://127.0.0.1:9808/readyz
curl http://127.0.0.1:9808/v1/status
/readyz should return 200. In Prometheus, query
up{job="monit-docker"} and monit_docker_ready{job="monit-docker"}; both
should be 1. up checks scraping, while monit_docker_ready checks fresh,
successful collection. Read the metrics reference for the full list.
If startup fails, inspect docker compose ps and
docker compose logs --tail=100 monit-docker prometheus grafana. The script
leaves the containers available for diagnosis. An unhealthy agent is not
automatically restarted solely because its health check fails; it retries
collection itself. See troubleshooting.
Ports, credentials and the Docker socket¶
Keep the generated password and optionally append these settings to .env:
MONIT_DOCKER_PORT=19808
PROMETHEUS_PORT=19090
GRAFANA_PORT=13000
DOCKER_SOCKET_PATH=/var/run/docker.sock
Run sh start.sh again after changes. Use the corresponding new port in your
browser and curl commands. If you use rootless Docker or a non-default local
socket, set DOCKER_SOCKET_PATH to its absolute path. A missing socket fails
startup instead of silently creating a directory. Remote Docker contexts and
Windows container daemons are outside this example’s scope.
Keep .env private; it is ignored by Git and excluded from source packages.
Grafana uses the environment password when initializing a new database. Editing
.env does not rotate a password already stored in Grafana: change it through
Grafana’s account settings and keep your stored credentials consistent. Do not
delete .env merely to change a password when reusing the Grafana volume.
To manage credentials yourself, create .env containing a nonempty
GRAFANA_ADMIN_PASSWORD before the first launch, then run sh start.sh. Without
the script, the equivalent launch command is
docker compose up -d --wait --wait-timeout 240 from this directory.
Stop, restart and remove data¶
Stop the stack while keeping its history and Grafana database:
docker compose down
Restart it with sh start.sh. Keep the same directory/project name so Compose
reattaches the same volumes. Changing the project name creates a separate stack
and separate volumes.
Only when you intend to delete this stack’s Prometheus history and Grafana database, run:
docker compose down --volumes
The generated .env remains on disk. Named volumes provide persistence, not
backups; archive them separately if you rely on this history.
Customize¶
The services are pinned to monit-docker 1.3.3, Prometheus 3.5.0 and Grafana 12.2.0.
Update versions deliberately in examples/monitoring/compose.yaml, then run
docker compose pull and sh start.sh. The repository-root docker-compose.yml
runs the minimal observation agent; use the file in examples/monitoring for this
separate stack. Stop the minimal stack first or change the published agent port.
The dashboard is mounted directly from examples/grafana/monit-docker.json.
Provisioned panels cannot be saved over from the Grafana UI; save a copy under a
different name/UID to customize it, or edit the source JSON. The single source
file remains the one validated by the dashboard tests.
To enable actions later, follow serve’s optional remediation guide:
add explicit rules, a persistent state-directory mount and --state-file, and
start with --dry-run. Prometheus alerts only report conditions; they do not
execute agent actions. Notification delivery requires a separately configured
Alertmanager; email and Slack examples are included.
Optional authentication for metrics¶
By default Prometheus can scrape /metrics without credentials. To protect
this endpoint, create a dedicated secret file with (umask 077; openssl rand -hex 32 > metrics-token) in a private directory. Mount
the resulting file read-only in both containers and pass
--metrics-token-file /run/secrets/metrics after monit-docker serve.
Add the following to the matching Prometheus scrape job:
authorization:
type: Bearer
credentials_file: /run/secrets/metrics
Use HTTPS when scraping across an untrusted network. The token only grants
access to metrics. For authenticated status reads, use the independent
--status-token-file option described in serve mode.