

Personally, I just have a couple of cheap CyberPower UPSs for my servers. I know I know, but I’m waiting for them to get old and die before I replace them with something better. My modem, router, and primary WiFi AP are on a custom LiFePO4-based UPS that I designed and built, because I felt like it. It’ll keep them running for around 10 hours, long past everything else in the house has shut down.
Sure, it’s a bit hack-and-slash, but not too bad. Honestly the dockcheck portion is already pretty complete, I’m not sure what all you could add to improve it. The custom plugin I’m using does nothing more than dump the array of container names with available updates to a comma-separated list in a file. In addition to that I also have a wrapper for dockcheck which does two things:
Basically there are 5 steps to the setup:
{ "metrics-addr": "127.0.0.1:9323" }
Once running, you should be able to run
curl http://localhost:9323/metrics
and see a dump of Prometheus metricssend_notification() { Updates=("$@") UpdToString=$(printf ", %s" "${Updates[@]}") UpdToString=${UpdToString:2} File=updatelist_local.txt echo -n $UpdToString > $File }
#!/bin/bash cd $(dirname $0) ./dockcheck/dockcheck.sh -mni if [[ -f updatelist_local.txt ]]; then mv updatelist_local.txt updatelist.txt else echo -n "None" > updatelist.txt fi
At this point you should be able to run your script, and at the end you’ll have the file “updatelist.txt” which will either contain a comma-separated list of all containers with available updates, or “None” if there are none. Add this script into cron to run on whatever cadence you want, I use 4 hours.
#!/usr/bin/python3 from flask import Flask, jsonify import os import time import requests import json app = Flask(__name__) # Listen addresses for docker metrics dockerurls = ['http://127.0.0.1:9323/metrics'] # Other dockerstats servers staturls = [] # File containing list of pending updates updatefile = '/path/to/updatelist.txt' @app.route('/metrics', methods=['GET']) def get_tasks(): running = 0 stopped = 0 updates = "" for url in dockerurls: response = requests.get(url) if (response.status_code == 200): for line in response.text.split("\n"): if 'engine_daemon_container_states_containers{state="running"}' in line: running += int(line.split()[1]) if 'engine_daemon_container_states_containers{state="paused"}' in line: stopped += int(line.split()[1]) if 'engine_daemon_container_states_containers{state="stopped"}' in line: stopped += int(line.split()[1]) for url in staturls: response = requests.get(url) if (response.status_code == 200): apidata = response.json() running += int(apidata['results']['running']) stopped += int(apidata['results']['stopped']) if (apidata['results']['updates'] != "None"): updates += ", " + apidata['results']['updates'] if (os.path.isfile(updatefile)): st = os.stat(updatefile) age = (time.time() - st.st_mtime) if (age < 86400): f = open(updatefile, "r") temp = f.readline() if (temp != "None"): updates += ", " + temp else: updates += ", Error" else: updates += ", Error" if not updates: updates = "None" else: updates = updates[2:] status = { 'running': running, 'stopped': stopped, 'updates': updates } return jsonify({'results': status}) if __name__ == '__main__': app.run(host='0.0.0.0')
The neat thing about this program is it’s nestable, meaning if you run steps 1-4 independently on all of your Docker servers (assuming you have more than one), then you can pick one of the machines to be the “master” and update the “staturls” variable to point to the other ones, allowing it to collect all of the data from other copies of itself into its own output. If the output of this program will only need to be accessed from localhost, you can change the host variable in app.run to 127.0.0.1 to lock it down. Once this is running, you should be able to run
curl http://localhost:5000/metrics
and see the running and stopped container counts and available updates for the current machine and any other machines you’ve added into “staturls”. You can then turn this program into a service or launch it @reboot in cron or in /etc/rc.local, whatever fits with your management style to start it up on boot. Note that it does verify the age of the updatelist.txt file before using it, if it’s more than a day old it likely means something is wrong with the dockcheck wrapper script or similar, and rather than using the output the REST API will print “Error” to let you know something is wrong.widget: type: customapi url: http://localhost:5000/metrics refreshInterval: 2000 display: list mappings: - field: results: running label: Running format: number - field: results: stopped label: Stopped format: number - field: results: updates label: Updates