Prometheus experiments with docker-compose
As 2018 rolls along the time has come to rebuild parts of my homelab again. This time I’m looking at my monitoring and metrics setup, which is based on sensu and graphite, and planning some experiments and evaluations using Prometheus. In this post I’ll show how I’m setting up my tests and provide the [Prometheus experiments with docker-compose](https://github.com/deanwilson/docker-compose- prometheus) source code in case it makes your own experiments a little easier to run.
This series continues in:
My starting requirements were fairly standard. I want to use containers
where possible. I want to test lots of different backends and I want to be able
to pick and choose which combinations of technologies I run for any
particular tests. As an example I have a few little applications that
make use of redis and some that use memcached, but I don’t want to be
committed to running all of the backing services for each smaller
experiment. In terms of technology I settled on docker-compose
to help
keep the container sprawl in check while also enabling me to specify all
the relationships. While looking into compose I found [Understanding
multiple Compose files](https://docs.docker.com/compose/extends/#multiple-compose-
files) and my basic structure began to emerge.
Starting with prometheus and grafana themselves I created the prometheus-server directory and added a basic prometheus config file to configure the service. I then added configuration for each of the things it was to collect from; prometheus and grafana in this case. Once these were in place I added the prometheus and grafana docker-compose.yaml file and created the stack.
docker-compose -f prometheus-server/docker-compose.yaml up -d
docker-compose -f prometheus-server/docker-compose.yaml ps
> docker-compose -f prometheus-server/docker-compose.yaml ps
Name Command State Ports
-----------------------------------------------------------------------
prometheusserver_grafana_1 /run.sh Up 0.0.0.0:3000->3000/tcp
prometheusserver_prometheus_1 /bin/prom ... Up 0.0.0.0:9090->9090/tcp
After manually configuring the prometheus data source in Grafana, all of which
is covered in the README
you have a working prometheus scraping itself and
grafana and a grafana that allows you to experiment with presenting the data.
While this is a good first step I need visibility into more than
the monitoring system itself, so it’s time to add another service. Keeping our
goal of being modular in mind I decided to break everything out into separate
directories and isolate the configuration. Adding a new service is as simple
as adding a redis-server
directory and writing a docker-compose file to run
redis and the prometheus exporter we use to get metrics from it. This part is
simple as most of the work is done for us. We use third party docker containers
and everything is up and running. But how do we add the redis exporter to the
prometheus targets? That’s where docker-composes merging behaviour shines.
In our base docker-compose.yaml
file we define the prometheus service and the
volumes assigned to it:
services:
prometheus:
image: prom/prometheus:v2.1.0
ports:
- 9090:9090
networks:
- public
volumes:
- prometheus_data:/prometheus
- ${PWD}/prometheus-server/config/prometheus.yml:/etc/prometheus/prometheus.yml
- ${PWD}/prometheus-server/config/targets/prometheus.json:/etc/prometheus/targets/prometheus.json
- ${PWD}/prometheus-server/config/targets/grafana.json:/etc/prometheus/targets/grafana.json
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
You can see we’re mounting individual target files in to prometheus for it to
probe. Now in our docker-compose-prometheus/redis-server/docker-compose.yaml
file
we’ll reference back to the existing prometheus service and add to the volumes
array.
prometheus:
volumes:
- ${PWD}/redis-server/redis.json:/etc/prometheus/targets/redis.json
Rather than overriding the array this incomplete service configuration adds another element to it. Allowing us to build up our config over multiple docker-compose files. In order for this to work we have to run the compose commands with each config specified every time. Resulting in the slightly hideous -
docker-compose \
-f prometheus-server/docker-compose.yaml \
-f redis-server/docker-compose.yaml \
up -d
Once you’re running a stack with 3 or 4 components you’ll probably
reach for aliases and add a base docker-compose
replacement
alias dc='docker-compose -f prometheus-server/docker-compose.yaml -f redis-server/docker-compose.yaml'
and then call that with actual commands like dc up -d
and dc logs
. Adding
your own application to the testing stack is as easy as adding a backing
resource. Create a directory and the two config files and everything should be hooked
in.
It’s early in the process and I’m sure to find issues with this naive approach but it’s enabled me to create arbitrarily complicated prometheus test environments and start evaluating its ecosystem of plugins and exporters. I’ll add more to it and refine where possible, the manual steps should hopefully be reduced by Grafana 5 for example, but hopefully it’ll remain a viable way for myself and others to run quick, adhoc tests.