Watchtower notifications via Shoutrrr (How-To) reddit / selfhosted ---------------------------------------------------------------------- Djaesthetic · 2023-12-18 03:41 I wanted to automate the updating of Docker containers on a schedule but couldn't find any "novice" how-to guides that covered everything. After some hours of trial & error I managed it but not before cursing several threads citing issues I'd ran in to but never updating with how that solved them. It inspired me to make a quick post to hopefully help the next person who goes searching. \--- **Watchtower** is the first piece, used to automate the updating of the Docker containers. It's fairly versatile re: the variables you can use to control its behavior. Here is a (*sanitized*) copy of my *docker-compose.yaml* file. services: watchtower: image: containrrr/watchtower:latest container_name: watchtower environment: - PUID=1000 - PGID=1000 - TZ=America/New_York - WATCHTOWER_CLEANUP=true - WATCHTOWER_INCLUDE_STOPPED=true - WATCHTOWER_REVIVE_STOPPED=false - WATCHTOWER_SCHEDULE=0 30 8 * * 1 - WATCHTOWER_NOTIFICATIONS=shoutrrr - WATCHTOWER_NOTIFICATION_URL=discord://TOKEN@WEBHOOKID command: - bazarr - nzbget - overseerr - plex - prowlarr - radarr - sonarr - unpackerr volumes: - /var/run/docker.sock:/var/run/docker.sock network_mode: host restart: unless-stopped In the config above, I've asked Watchtower to: 1. **(WATCHTOWER\_CLEANUP)** Removes old images after updating a container to use a newer one. 2. **(WATCHTOWER\_INCLUDE\_STOPPED)** Updates stopped containers as well. 3. **(WATCHTOWER\_REVIVE\_STOPPED)** Will *NOT* start any stopped containers that have their image updated. If set to true it *would* start them regardless of their state. 4. **(WATCHTOWER\_SCHEDULE)** This follows Cron Job Formatting (*adding a 6th digit at the beginning to represent seconds*). I've configured mine to run every Monday at 8:30AM. Here is [**AN EXCELLENT SITE**](https://linuxiac.com/cron-job-format/) that explains Cron Job Format. 5. **(WATCHTOWER\_NOTIFICATIONS)** This config sends notifications of updated containers through a Discord channel (*via ANOTHER container called* ***Shoutrrr***). This was the trickiest part as every tutorial I found used Email. More on this piece below. 6. **(command)** By default Watchtower monitors *all* containers however I only wanted to target specific ones. It is very flexible in how it can be configured (*such as manual inclusions and exclusions via 'label' environment variables*). The approach above is what works best for my use case. I found [**THIS EXCELLENT TUTORIAL**](https://linuxiac.com/watchtower- automatically-update-docker-container-images/) that explains many useful arguments for customizing the behavior to your specific needs. [**HERE**](https://containrrr.dev/watchtower/arguments/) is also a complete list of *every* argument you can use. \---- **Shoutrrr** (*another container*) was the second piece, used as a notification service for other apps to call. This was slightly trickier than anticipated. It's important to note **Shoutrrr** is *NOT* expected to run full time. **Watchtower** calls upon it (*like a CLI command*) whenever needed. My *docker-compose.yaml* file for **Shoutrrr** couldn't have been any simpler. The container simply needs to exist. services: shoutrrr: image: containrrr/shoutrrr:latest container_name: shoutrrr environment: - PUID:1000 - PGID:1000 - TZ=America/New_York network_mode: host **Shoutrrr** is extremely versatile in that it can be configured to proxy notifications through [**DOZENS OF SERVICES**](https://containrrr.dev/shoutrrr/v0.8/). In wanted to send through Discord via a webhook. The **Shoutrrr** 'Services' documentation in the link provided had a great walkthrough, especially regarding the formatting of the TOKEN & WEBHOOK ID in the service URL (*see the very bottom of their doc*). Specifically -- THE WEBHOOK URL DISCORD PROVIDES YOU: https://discord.com/api/webhooks/WEBHOOKID/TOKEN HOW **SHOUTRRR** EXPECTS IT DEFINED IN YOUR **WATCHTOWER\_NOTIFICATION\_URL**: discord://TOKEN@WEBHOOKID (*You'll note how the TOKEN & WEBHOOK ID placement are swapped. Don't mix them up!*) \--- Hopefully some or all of this walkthrough will help speed things along for the next person who comes along looking to do similar. ---------------------------------------------------------------------- getgoingfast · 2023-12-18 05:45 Neat writeup there, too job. Have not used Shoutrrr but I imagine it is similar to Gotify? Been using Gotify notifications with Watchtower and for the life of me could not figure how to change the notification priority to buzz the phone. Good to see we have alternatives. ---------------------------------------------------------------------- Orbe112 · 2023-12-18 06:03 do you mind explaining to 5 years old me what Shoutrrr are and can do? I have watchtower set up to give the update in a discord channel, but looking to change to email or something else as I would like to get the status when I wake up in the morning without checking discord, as I do not have notfications on for that. ---------------------------------------------------------------------- SnowyLocksmith · 2023-12-18 06:04 For gotify, in the webportal you can set a default priority to a application. ---------------------------------------------------------------------- SnowyLocksmith · 2023-12-18 06:05 Great writeup, I have a somewhat similar setup. Only difference is, I send notifications to my discord directly from watchtower, shoutrr isnt really needed. ---------------------------------------------------------------------- ExcessiveEscargot · 2023-12-18 06:10 Shoutrrr centralises/proxies notifications. ---------------------------------------------------------------------- Djaesthetic · 2023-12-18 06:12 I saw that but opted to dig in on forcing myself toward the Shoutrrr route b/c it’s listed as “*legacy notifications for backward compatibility*” in their documentation. Seems like more often than not that’s code slang for “*we’re deprecating this function soon so don’t get used to it*”. Heh Who knows how long they’ll leave it be. I just didn’t wanna risk it with a new setup. ---------------------------------------------------------------------- Orbe112 · 2023-12-18 06:12 And what are the benefits for me vs just using discord or email? ---------------------------------------------------------------------- getgoingfast · 2023-12-18 06:15 You're right and something I tried already. Unfortunately that feature does not work as expected. I would imagine the original intent of this feature was to set priority at global level, but it simply doesn't change anything. Even if I set priority as 0, my phone notification would buzz like it does for Priority 10. And all Gotify notifications goes as 0, even if I set 10 on Gotify's webportal. ---------------------------------------------------------------------- SnowyLocksmith · 2023-12-18 07:05 Fair Enough. I am running my stuff on a Pi 4, and didn't want any extra containers unless absolutely necessary, as I am already running a lot of other stuff lol ---------------------------------------------------------------------- SnowyLocksmith · 2023-12-18 07:06 That's strange. Did you try checking in your phone setting for different types of notification categories the process? In android, for each priority you can set rules. ---------------------------------------------------------------------- getgoingfast · 2023-12-18 07:17 Good point, never thought about it. Just tested it with Proxmox test notification and it works. Thanks! ---------------------------------------------------------------------- ExcessiveEscargot · 2023-12-18 07:26 That's something only you can answer, how would I know? It's a tool designed to centralise a bunch of different notification pathways into a single place; if you're only using discord or email then there doesn't seem like much need for it? ---------------------------------------------------------------------- Calm-Size-1110 · 2023-12-18 08:33 I don't think you need the shoutrr container. Below is my setup and it able to send the notification just fine: ``` watchtower: image: containrrr/watchtower container_name: watchtower volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - WATCHTOWER_SCHEDULE=0 0 20 * * * - TZ=Asia/Kuala_Lumpur - WATCHTOWER_NOTIFICATIONS_HOSTNAME=nuc - WATCHTOWER_CLEANUP=true - WATCHTOWER_INCLUDE_RESTARTING=true - WATCHTOWER_NOTIFICATIONS=shoutrrr #- WATCHTOWER_NOTIFICATION_URL=telegram://121xxxxx9:AAH3p1xxxxxx xxxxxxxxxxxcGkV8fO_2zI@telegram/?channels=441xxxxxx56 - WATCHTOWER_NOTIFICATION_URL=smtp://xxxxx@gmail.com:xsmtpsib- 0df33185xxxxxx142cdc9254dbb6bedc9f10dc87xxxxxx8c08d- TaL1GwCHzxxxxx8k@smtp- relay.sendinblue.com:587/?from=xxx@mail.com&to=xxx@mail.com ``` ---------------------------------------------------------------------- Kooky_Percentage3687 · 2023-12-18 08:48 As mentioned, you don't need shoutrrr to get discord notifications, it will work OTB. It's also worth noting, watchertower's cron format uses "spring" which is slightly different (includes seconds unlike regular cron expressions) ---------------------------------------------------------------------- Djaesthetic · 2023-12-18 13:37 Ever since some of the other comments I’ve been second guessing if it was just syntax errors until I got it right, i.e. if the library is embedded. Gonna test here in a bit and update accordingly if need be. ---------------------------------------------------------------------- Nitro2985 · 2023-12-18 21:27 I never auto-update containers for docker (though I do on a CoreOS VM as it's supposed to be completely hands off) ​ I do have a bash script that will increment through all the subdirectories in a folder with a docker compose file in them, pull the new image, bring down the old stack, bring up the new one, and then clean up the unused images when it's done though. ​ Drop this in the directory like this: \~/compose-files/docker\_update.sh and then you should have other directories in there like: \~/compose-files/gitea/docker-compose.yml \~/compose-files/syncthing/docker-compose.yml etc. ​ #!/bin/bash # Function to update docker-compose.yml file in a directory update_docker_compose() { local directory="$1" # Change to the directory cd "$directory" || return # Check if docker-compose.yml file exists if [ -f "docker-compose.yml" ]; then echo "Updating docker-compose.yml in $directory" # Pull the latest images docker-compose pull # Recreate and start the containers in the background docker-compose up -d fi # Go back to the original directory cd - > /dev/null || return } # Recursive function to search and update docker-compose.yml files search_and_update() { local directory="$1" # Iterate over each entry in the directory for entry in "$directory"/*; do if [ -d "$entry" ]; then # Directory found, recursively search inside it search_and_update "$entry" fi done # Update docker-compose.yml in the current directory update_docker_compose "$directory" } # Start the search and update process from the current directory search_and_update . # Prune images after update docker image prune -f