What's up docker? How to keep your containers up to date

Thanks for the support!

I added the --net=host setting to the above run command and I think that’s working now. I see the mqtt messages in my broker now.

I’m still confused about why the watcher I created doesn’t seem to work. It’s still saying “no watcher found”. Did I do something wrong there?

I’m glad to see that it’s working for you!
About your watcher, I found the issue ; it’s now fixed in the latest version (1.0.1)

seems to be working now.

Thanks!

Do you have an example of a working HA notification from MQTT by chance?

I’m sure I could suss one out but if you already have one then why re-invent the wheel? :wink:

Sorry, I don’t have any ready-to-go example to share… I haven’t integrated WUD to HASS yet (I’m using the WUD email trigger to be notified).

No problem. I just figured I’d ask first before digging in.

A very interesting project.

I do agree with your drawbacks regarding Watchtower and Ouroboros. Maybe we should mention Diun too as an alternative. Indeed I believe an automated upgrade is in general not something you should want, and therefore I concentrate on the notification options of all different systems. My main use case that i would like to implement is creating sensors per container and manually press a button when i would like to update the container, after a backup, and a verification of that updated system. Updating itself is not a complex operation, so no direct need to have that in the monitoring software, but it can be an extra advantage.

For Watchtower the most suitable option for that seems to be the lifecycle configurations that calls plain sh scripts. I could however not find any working samples of that, because the sh command is not available in the standard docker container (which uses ash).

Ouroboros uses apprise as notification system, which has a lot of notification options, even native Home Assistant notifications, although I did not look into detail how to configure that. It has some dry run option, that may be used for notification only.

Then both Diun and Whats’up Docker have Webhook or MQTT notifications that could do the job. My main issue with the way both are implemented is that a generic notification is sent and so address a single sensor. So for example when two containers have newer versions and when I configured for example MQTT, my sensor would shortly give the first container outdated, but the second container will remain on that MQTT sensor and first is overwritten with the last update message.

Because I prefer a separate sensor for each container, I don’t see a way how to implement this with this single topic or webhook notification. What should be the approach to have separate sensors. Or should I raise a feature request to sent notifications based on the container name to different MQTT topics or Webhooks?

Thanks.

Thank you for your interest!

Just to clarify; I didn’t mention Diun at that time because it didn’t exist while I’d started my project.

But you’re right: Diun and Wud shares the same philosophy.

Regarding your issue, your proposal to separate notifications per image is very interesting.

For MQTT, I could change from a single wud/image topic
to wud/image/$organization/$image/$version topics

e.g.
wud/image/homeassistant/home-assistant/2021.4.3

(for backward compatibility, current users will have to subscribe to wud/image/# to get all notifications at once as now)

I’ m not sure if I just enforce the topic naming or if I offer end-users the possibility to write their own patterns (using a simple placeholder syntax).
e.g.
env WUD_TRIGGER_MQTT_MOSQUITTO_TOPIC=wud/#organization_#image_#version
which will result as notifications sent to a wud/homeassistant_home-assistant_2021.4.3 topic

Regarding the webhook part, I don’t really get your issue because I don’t understand how you consider integrating WUD to HASS.

Do you want WUD to call HASS using HTTP to notify of new image versions?
If so, the WUD Http trigger should do the trick, isn’t it?
Even if there is a single URL, the Http Request contains the info about which image is involved (info present in a query param or in the request body).

But for that one too, I could imagine a solution where end-users can write their own URL patterns (using a simple placeholder syntax).
e.g.
env WUD_TRIGGER_HTTP_MYREMOTEHOST_URL=https://myhook/wud/#organization/#image/#version
which will result as notifications sent to a https://myhook/wud/homeassistant/home-assistant/2021.4.3 url

What do you think?
I’d be really happy to fulfill your request; can you open an issue on Github to continue the discussion and find the best solution?

Thanks!

Thanks for your answer. I will continue on GitHub.

@fmartinou I’m also interested in container specific notifications.

#version in the topic might be painful so maybe just: wud/$image ($serviceName would be even better)?

In order to make a binary sensor easy to create, ideally there would be a Bool in there somewhere as well such as: “updateAvailable”:“true”

Thanks for your recommendations!
Now I need to find some spare time to start implementing a solution.
In the meantime, feel free to add comments on GitHub to share your thoughts.
I let you know when I get something ready to test.

Hi @eiri @leighcurran ,

A first implementation is available!
Please find all the details on Github.

Any feedback will be much appreciated!

What it looks like on my own hass instance.

1 Like

Amazing! My entire network is made up of Docker containers running on many proxmox LXC’s and a Pi4. This will make it much easier to see when updates are available.

I’ll test this shortly and help with feedback. Thanks for your hard work!

1 Like

Now that I see this thread alive again I have been having a problem running this for a while now but never got around to trying to fix it. I’ve actually had it disabled for a loing time now so I can’t remember the original issue.

So I updated the image for wud today and when it restarted I keep getting these errors in the containers logs:

{"name":"whats-up-docker","hostname":"NUC","pid":1,"level":30,"msg":"What's up, docker? is starting","time":"2021-04-27T21:35:13.815Z","v":0}
{"name":"whats-up-docker","hostname":"NUC","pid":1,"level":30,"msg":"Init DB (/store/wud.json)","time":"2021-04-27T21:35:13.817Z","v":0}
{"name":"whats-up-docker","hostname":"NUC","pid":1,"level":30,"msg":"Init Prometheus module","time":"2021-04-27T21:35:13.824Z","v":0}
{"name":"whats-up-docker","hostname":"NUC","pid":1,"level":20,"msg":"Start image metrics interval","time":"2021-04-27T21:35:13.832Z","v":0}
(node:1) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'localeCompare' of undefined
    at /home/node/app/node_modules/sort-es/lib/index.cjs.js:120:46
    at /home/node/app/node_modules/sort-es/lib/index.cjs.js:76:36
    at Array.sort (<anonymous>)
    at Object.getImages (/home/node/app/store/index.js:150:22)
    at populateGauge (/home/node/app/prometheus/image.js:12:11)
    at Object.init (/home/node/app/prometheus/image.js:61:5)
    at Object.init (/home/node/app/prometheus/index.js:15:11)
    at main (/home/node/app/index.js:14:16)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:1) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
/home/node/app/node_modules/sort-es/lib/index.cjs.js:120
        return sort(fixString(first, options).localeCompare(fixString(second, options)), options);
                                               ^
TypeError: Cannot read property 'localeCompare' of undefined
    at /home/node/app/node_modules/sort-es/lib/index.cjs.js:120:46
    at /home/node/app/node_modules/sort-es/lib/index.cjs.js:76:36
    at Array.sort (<anonymous>)
    at Object.getImages (/home/node/app/store/index.js:150:22)
    at Timeout.populateGauge [as _onTimeout] (/home/node/app/prometheus/image.js:12:11)
    at listOnTimeout (internal/timers.js:554:17)
    at processTimers (internal/timers.js:497:7)

Here is my docker run command:

docker run -d --name wud --network=host --restart unless-stopped -e WUD_LOG_LEVEL="DEBUG" -v "/var/run/docker.sock:/var/run/docker.sock" -v /home/finity/docker/wud/store:/store -e WUD_WATCHER_DOCKER_LOCAL_CRON="1 * * * *" -e WUD_TRIGGER_MQTT_MOSQUITTO_URL="mqtt://192.168.1.11:1883" -e WUD_TRIGGER_MQTT_MOSQUITTO_USER="my_user" -e WUD_TRIGGER_MQTT_MOSQUITTO_PASSWORD="my_password" -e WUD_TRIGGER_MQTT_MOSQUITTO_TOPIC="wud/image" fmartinou/whats-up-docker

any idea what I need to do to fix it?

I’d like to start using it again and the new binary sensor looks really useful.

I see that you’re persisting the wud state in a mounted volume.
Because you just upgraded from an old version to the latest one, you’re probably facing errors because the storage format has been changed.
I suggest you to clear the content of the /store volume and restart the service.

Please also notice that if you want to try the new hass integration, you need to use the ‘develop’ tag and not the ‘latest’ one.

Right I just wanted on get this running on latest before I moved to the dev version.

I think it seems to be working now.

Now I just need to figure out how to filter the containers to only watch for the correct new version types.

I believe I run the “latest” tag of every container except HA related ones and those are “versioned” containers.

My advices:

  1. Try to find immutable versions for the containers you run and get rid of latest tags as much as possible.

  2. Then using Docker labels on your containers, you’ll be able to fine-tune the expected format of the newer tags.

Below some examples for popular services:

version: '3'

services:

    bitwarden:
        image: bitwardenrs/server:1.20.0-alpine
        labels:
            - 'wud.tag.include=^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)-alpine$$'

    duplicati:
        image: linuxserver/duplicati:v2.0.5.1-2.0.5.1_beta_2020-01-18-ls96
        labels:
            - 'wud.tag.include=^v[0-9]\d*\.[0-9]\d*\.[0-9]\d*\.[0-9]\d*-[0-9]\d*\.[0-9]\d*\.[0-9]\d*\.[0-9]\d*.*$$'

    homeassistant:
        image: homeassistant/home-assistant:2021.4.6
        labels:
            - 'wud.tag.include=^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)$$'

    homeassistant_db:
        image: mariadb:10.5.8
        labels:
            - 'wud.tag.include=^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)$$'

    mosquitto:
        image: eclipse-mosquitto:2.0.10
        labels:
            - 'wud.tag.include=^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)$$'

    nextcloud:
        image: nextcloud:21.0.0
        labels:
            - 'wud.tag.include=^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)$$'

    nextcloud_db:
        image: mariadb:10.5.8
        labels:
            - 'wud.tag.include=^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)$$'

    photoprism:
        image: photoprism/photoprism:20210426
        labels:
            - 'wud.tag.include=^([0-9]{8})$$'

    photoprism_db:
        image: mariadb:10.5.8
        labels:
            - 'wud.tag.include=^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)$$'

    pihole:
        image: pihole/pihole:v5.7
        labels:
            - 'wud.tag.include=^v(0|[1-9]\d*)\.(0|[1-9]\d*)$$'

    plex:
        image: linuxserver/plex:1.22.3.4392-d7c624def-ls44
        labels:
            - 'wud.tag.include=^[0-9]\d*\.[0-9]\d*\.[0-9]\d*\.[0-9]\d*-[0-9a-z]*-ls[0-9]\d*$$'

    portainer:
        image: portainer/portainer-ce:2.1.1-alpine
        labels:
            - 'wud.tag.include=^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)-alpine$$'

    traefik:
        image: traefik:2.4.8
        labels:
            - 'wud.tag.include=^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)$$'

    whatsupdocker:
        image: fmartinou/whats-up-docker:3.4.0
        labels:
            - 'wud.tag.include=^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)$$'
1 Like

I don’t understand what you are saying here.

Why would I need to get rid of the “latest” tags? Why is using those bad?

And if I use the actual version for each image in my docker config wouldn’t I need to manually change that every time I update a container so it pulls the newer image?

1 Like

With latest you have no guarantee that something which was working few weeks ago is still working if you redeploy it; that’s a major issue for me.

Version immutability is the key factor to get a stable system.

Here is a good blog post describing why latest is a bad practice:

That’s the main reason why I’ve coded WUD and why I couldn’t rely on tools like Ouroboros or Watchtower.

WUD is specialized in semver version comparison so if you only use latest versions, it’s useless for you.

And if I use the actual version for each image in my docker config wouldn’t I need to manually change that every time I update a container so it pulls the newer image?

Yes, if you use Docker Compose, your docker-compose.yml file can easily be tracked on Git.
So you’re always sure to have a descriptor which is working.
And you can easily rollback in case of problems…

The update process is really easy too and you’re in total control:

  1. Change a tag version in a compose.yml file
  2. Run docker-compose up -d --remove-orphans

…And let Docker Compose pull the new image, remove the old container and deploy the new one!

Wow, I guess I’ve been really lucky then.

I’ve used “latest” ever since I started using HA in docker over two years ago and I use Portainer to occasionally pull a new image of all 28 containers I’m running and I’ve rarely had any issues.

I have had to downgrade a version of HA because of breaking changes once or twice in that time but I always revert to using the “latest” tag after HA gets their issues sorted out.

And I don’t use docker-compose. I just use a docker run command for each individual container I run.

So there is no way at all for WUD to know if there is a new “latest” image tag?