Compare commits

...

27 Commits

Author SHA1 Message Date
mag37
09c9faa008 Merge pull request #109 from mag37/feedback_podcheck
jq rewrite and formatting fixes
2024-11-20 08:39:30 +01:00
mag37
17ed46d157 Merge branch 'main' into feedback_podcheck 2024-11-20 08:38:49 +01:00
mag37
d744d51473 jq version bump 2024-11-18 21:13:44 +01:00
mag37
3821c22660 generalized variable name 2024-11-18 21:04:02 +01:00
mag37
5dd42b7336 changed to jq metadata check 2024-11-18 21:01:13 +01:00
mag37
8da2cbe611 Converted to jq metadata check.
Added jq binary check, fixed consistent command -v syntax.
2024-11-18 20:04:08 +01:00
mag37
9937d6bc3f minor readme updates 2024-11-17 20:43:22 +01:00
mag37
5517abb090 formatting to match improvements in podcheck fork 2024-11-17 14:54:28 +01:00
mag37
cb8c23e62d Update README.md
Added urls to podman fork
2024-11-16 20:39:51 +01:00
mag37
0009adc2cf Update urls.list
added vaultwarden-backup
2024-11-06 08:49:59 +01:00
mag37
8d39e1b66b new example-file 2024-10-21 20:51:23 +02:00
mag37
ec068dd19a Fixed typo. 2024-10-14 06:28:35 +02:00
mag37
119932aa19 Update README.md
added Discord to the notifications list.
2024-10-13 22:28:39 +02:00
mag37
a9f2433fab Merge pull request #104 from mag37/notify-rewrite
Complete rewrite of notify function, all templates adjusted + more.
2024-10-13 17:36:41 +02:00
mag37
18e467274e edited changenotes 2024-10-13 17:11:10 +02:00
mag37
6db92be627 getting ready for merge 2024-10-12 13:13:11 +02:00
mag37
fc47b1313b finalizing formatting and edits 2024-10-10 10:22:17 +02:00
mag37
76d2921719 fixed MSMTP-typo 2024-10-10 09:48:41 +02:00
mag37
2844e54fbd Merge pull request #102 from thomas-mc-work/patch-1
fix upgly typo which prevents email notifications
2024-10-08 22:05:53 +02:00
Thomas McWork
e0d66cc773 fix upgly typo which prevents email notifications 2024-10-08 21:57:23 +02:00
mag37
071fa4b245 changed regctl verbosity 2024-10-08 09:41:32 +02:00
mag37
cb73025a61 added discord template 2024-10-07 21:31:33 +02:00
mag37
87f1886d28 releasenotes rewritten to array 2024-10-07 21:29:49 +02:00
mag37
ac10a96cc8 all template rewritten, some guesswork 2024-10-07 21:28:31 +02:00
mag37
e5a7a715c6 Merge pull request #99 from lpukatch/release-note-urls
add release note urls
2024-10-05 21:26:31 +02:00
mag37
8a6a1fbec2 Update urls.list 2024-10-05 21:26:07 +02:00
lpukatch
04b0c46366 add release note urls for popular services 2024-10-05 09:36:06 -04:00
17 changed files with 198 additions and 118 deletions

View File

@@ -13,16 +13,22 @@
<h3 align="center">CLI tool to automate docker image updates. <br>No <b>pre-pull</b>, selective, optional notifications and prune when done.</h3>
<h2 align="center">Now with simple notification integrations!</h2>
<h4 align="center">With features like excluding specific containers, custom container labels, auto-prune when done and more.</h4>
<h4 align="center">Also see the fresh Podman fork <a href="https://github.com/sudo-kraken/podcheck">sudo-kraken/podcheck</a>!</h4>
___
## :bell: Changelog
- **v0.5.1**: DEPENDENCY WARNING: now requires **jq**. + Upstreaming changes from [sudo-kraken/podcheck](https://github.com/sudo-kraken/podcheck)
- **v0.5.0**: Rewritten notify logic - all templates are adjusted and should be migrated!
- Copy the custom settings from your current template to the new version of the same template.
- Look into, copy and customize the `urls.list` file if that's of interest.
- Other changes:
- Added Discord notify template.
- Verbosity changed of `regctl`.
- **v0.4.9**: Added a function to enrich the notify-message with release note URLs. See [Release notes addon](https://github.com/mag37/dockcheck#date-release-notes-addon-to-notifications)
- **v0.4.8**: Rewrote prune logic to not prompt with options `-a|-y` or `-n`. Auto prune with `-p`.
- **v0.4.7**: Notification Template changes to gotify(new!), DSM(improved), SMTP(deprecation alternative).
- **v0.4.6**: Compatibility changes to timeout, due to busybox.
- **v0.4.5**: Bugfixes, compatibility changes to timeout and arrays.
- **v0.4.3**: Added timeout option to skip container if registry check takes too long (10s default).
___
@@ -68,13 +74,13 @@ Containers with updates available:
Choose what containers to update:
Enter number(s) separated by comma, [a] for all - [q] to quit:
```
Then it proceedes to run `pull` and `up -d` on every container with updates.
Then it proceeds to run `pull` and `up -d` on every container with updates.
After the updates are complete, you'll get prompted if you'd like to prune dangling images.
___
## :nut_and_bolt: Dependencies
- Running docker (duh) and compose, either standalone or plugin.
- Running docker (duh) and compose, either standalone or plugin. (see [Podman fork](https://github.com/sudo-kraken/podcheck)
- Bash shell or compatible shell of at least v4.3
- [regclient/regctl](https://github.com/regclient/regclient) (Licensed under [Apache-2.0 License](http://www.apache.org/licenses/LICENSE-2.0))
- User will be prompted to download `regctl` if not in `PATH` or `PWD`.
@@ -111,13 +117,14 @@ Use a `notify_X.sh` template file from the **notify_templates** directory, copy
- [Telegram](https://telegram.org/) - Telegram chat API.
- [Matrix-Synapse](https://github.com/element-hq/synapse) - [Matrix](https://matrix.org/), open, secure, decentralised communication.
- [Pushover](https://pushover.net/) - Simple Notifications (to your phone, wearables, desktops)
- [Discord](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) - Discord webhooks.
Further additions are welcome - suggestions or PR!
<sub><sup>Initiated and first contributed by [yoyoma2](https://github.com/yoyoma2).</sup></sub>
### :date: Release notes addon to Notifications
There's a function to use a lookup-file to add release note URL's to the notification message.
Copy the notify_templates/`urls.list` file to the script directory and modify it as necessary, it will be used automatically if it's there.
Copy the notify_templates/`urls.list` file to the script directory, it will be used automatically if it's there. Modify it as necessary, the names of interest in the left column needs to match your container names.
The output of the notification will look something like this:
```
Containers on hostname with updates available:

View File

@@ -1,19 +1,19 @@
#!/usr/bin/env bash
VERSION="v0.4.9"
### ChangeNotes: Added a function to enrich the notify-message with release note URLs. See README.
VERSION="v0.5.1"
# ChangeNotes: DEPENDENCY WARNING: now requires jq. And upstreaming changes from sudo-kraken/podcheck
Github="https://github.com/mag37/dockcheck"
RawUrl="https://raw.githubusercontent.com/mag37/dockcheck/main/dockcheck.sh"
### Variables for self updating
# Variables for self updating
ScriptArgs=( "$@" )
ScriptPath="$(readlink -f "$0")"
ScriptWorkDir="$(dirname "$ScriptPath")"
### Check if there's a new release of the script:
# Check if there's a new release of the script
LatestRelease="$(curl -s -r 0-50 $RawUrl | sed -n "/VERSION/s/VERSION=//p" | tr -d '"')"
LatestChanges="$(curl -s -r 0-200 $RawUrl | sed -n "/ChangeNotes/s/### ChangeNotes: //p")"
LatestChanges="$(curl -s -r 0-200 $RawUrl | sed -n "/ChangeNotes/s/# ChangeNotes: //p")"
### Help Function:
# Help Function
Help() {
echo "Syntax: dockcheck.sh [OPTION] [part of name to filter]"
echo "Example: dockcheck.sh -y -d 10 -e nextcloud,heimdall"
@@ -27,9 +27,9 @@ Help() {
echo "-i Inform - send a preconfigured notification."
echo "-l Only update if label is set. See readme."
echo "-m Monochrome mode, no printf color codes."
echo "-n No updates, only checking availability."
echo "-p Auto-Prune dangling images after update."
echo "-r Allow updating images for docker run, wont update the container."
echo "-n No updates; only checking availability."
echo "-p Auto-prune dangling images after update."
echo "-r Allow updating images for docker run; won't update the container."
echo "-s Include stopped containers in the check. (Logic: docker ps -a)."
echo "-t Set a timeout (in seconds) per container for registry checkups, 10 is default."
echo "-v Prints current version."
@@ -37,7 +37,7 @@ Help() {
echo "Project source: $Github"
}
### Colors:
# Colors
c_red="\033[0;31m"
c_green="\033[0;32m"
c_yellow="\033[0;33m"
@@ -68,18 +68,19 @@ while getopts "aynpfrhlisvme:d:t:" options; do
done
shift "$((OPTIND-1))"
# Self-update function
self_update_curl() {
cp "$ScriptPath" "$ScriptPath".bak
if [[ $(builtin type -P curl) ]]; then
if [[ $(command -v curl) ]]; then
curl -L $RawUrl > "$ScriptPath" ; chmod +x "$ScriptPath"
printf "\n%s\n" "--- starting over with the updated version ---"
exec "$ScriptPath" "${ScriptArgs[@]}" # run the new script with old arguments
exit 1 # exit the old instance
elif [[ $(builtin type -P wget) ]]; then
exit 1 # Exit the old instance
elif [[ $(command -v wget) ]]; then
wget $RawUrl -O "$ScriptPath" ; chmod +x "$ScriptPath"
printf "\n%s\n" "--- starting over with the updated version ---"
exec "$ScriptPath" "${ScriptArgs[@]}" # run the new script with old arguments
exit 1 # exit the old instance
exit 1 # Exit the old instance
else
printf "curl/wget not available - download the update manually: %s \n" "$Github"
fi
@@ -87,7 +88,7 @@ self_update_curl() {
self_update() {
cd "$ScriptWorkDir" || { printf "Path error, skipping update.\n" ; return ; }
if [[ $(builtin type -P git) ]] && [[ "$(git ls-remote --get-url 2>/dev/null)" =~ .*"mag37/dockcheck".* ]] ; then
if [[ $(command -v git) ]] && [[ "$(git ls-remote --get-url 2>/dev/null)" =~ .*"mag37/dockcheck".* ]] ; then
printf "\n%s\n" "Pulling the latest version."
git pull --force || { printf "Git error, manually pull/clone.\n" ; return ; }
printf "\n%s\n" "--- starting over with the updated version ---"
@@ -100,7 +101,7 @@ self_update() {
fi
}
### Choose from list -function:
# Choose from list function
choosecontainers() {
while [[ -z "$ChoiceClean" ]]; do
read -r -p "Enter number(s) separated by comma, [a] for all - [q] to quit: " Choice
@@ -112,7 +113,7 @@ choosecontainers() {
else
ChoiceClean=${Choice//[,.:;]/ }
for CC in $ChoiceClean ; do
if [[ "$CC" -lt 1 || "$CC" -gt $UpdCount ]] ; then # reset choice if out of bounds
if [[ "$CC" -lt 1 || "$CC" -gt $UpdCount ]] ; then # Reset choice if out of bounds
echo "Number not in list: $CC" ; unset ChoiceClean ; break 1
else
SelectedUpdates+=( "${GotUpdates[$CC-1]}" )
@@ -126,7 +127,7 @@ choosecontainers() {
}
datecheck() {
ImageDate=$($regbin image inspect "$RepoUrl" --format='{{.Created}}' | cut -d" " -f1 )
ImageDate=$($regbin -v error image inspect "$RepoUrl" --format='{{.Created}}' | cut -d" " -f1 )
ImageAge=$(( ( $(date +%s) - $(date -d "$ImageDate" +%s) )/86400 ))
if [ "$ImageAge" -gt "$DaysOld" ] ; then
return 0
@@ -139,26 +140,26 @@ progress_bar() {
QueCurrent="$1"
QueTotal="$2"
((Percent=100*QueCurrent/QueTotal))
((Complete=50*Percent/100)) # change first number for width (50)
((Left=50-Complete)) # change first number for width (50)
((Complete=50*Percent/100)) # Change first number for width (50)
((Left=50-Complete)) # Change first number for width (50)
BarComplete=$(printf "%${Complete}s" | tr " " "#")
BarLeft=$(printf "%${Left}s" | tr " " "-")
[[ "$QueTotal" == "$QueCurrent" ]] || printf "\r[%s%s] %s/%s " "$BarComplete" "$BarLeft" "$QueCurrent" "$QueTotal"
[[ "$QueTotal" == "$QueCurrent" ]] && printf "\r[%b%s%b] %s/%s \n" "$c_teal" "$BarComplete" "$c_reset" "$QueCurrent" "$QueTotal"
}
### Function to add user-provided urls to releasenotes
# Function to add user-provided urls to releasenotes
releasenotes() {
for update in ${Updates[@]}; do
for update in ${GotUpdates[@]}; do
found=false
while read -r container url; do
[[ $update == $container ]] && printf "%s -> %s\n" "$update" "$url" && found=true
[[ $update == $container ]] && Updates+=("$update -> $url") && found=true
done < "$ScriptWorkDir"/urls.list
[[ $found == false ]] && printf "%s -> url missing\n" "$update" || continue
[[ $found == false ]] && Updates+=("$update -> url missing") || continue
done
}
### Version check & initiate self update
# Version check & initiate self update
if [[ "$VERSION" != "$LatestRelease" ]] ; then
printf "New version available! %b%s%b ⇒ %b%s%b \n Change Notes: %s \n" "$c_yellow" "$VERSION" "$c_reset" "$c_green" "$LatestRelease" "$c_reset" "$LatestChanges"
if [[ -z "$AutoUp" ]] ; then
@@ -167,26 +168,26 @@ if [[ "$VERSION" != "$LatestRelease" ]] ; then
fi
fi
### Set $1 to a variable for name filtering later.
# Set $1 to a variable for name filtering later
SearchName="$1"
### Create array of excludes
# Create array of excludes
IFS=',' read -r -a Excludes <<< "$Exclude" ; unset IFS
### Check if required binary exists in PATH or directory:
if [[ $(builtin type -P "regctl") ]]; then regbin="regctl" ;
# Check if required binary exists in PATH or directory
if [[ $(command -v regctl) ]]; then regbin="regctl" ;
elif [[ -f "$ScriptWorkDir/regctl" ]]; then regbin="$ScriptWorkDir/regctl" ;
else
read -r -p "Required dependency 'regctl' missing, do you want it downloaded? y/[n] " GetDep
if [[ "$GetDep" =~ [yY] ]] ; then
### Check arch:
# Check architecture
case "$(uname --machine)" in
x86_64|amd64) architecture="amd64" ;;
arm64|aarch64) architecture="arm64";;
*) echo "Architecture not supported, exiting." ; exit 1;;
esac
RegUrl="https://github.com/regclient/regclient/releases/latest/download/regctl-linux-$architecture"
if [[ $(builtin type -P curl) ]]; then curl -L $RegUrl > "$ScriptWorkDir/regctl" ; chmod +x "$ScriptWorkDir/regctl" ; regbin="$ScriptWorkDir/regctl" ;
elif [[ $(builtin type -P wget) ]]; then wget $RegUrl -O "$ScriptWorkDir/regctl" ; chmod +x "$ScriptWorkDir/regctl" ; regbin="$ScriptWorkDir/regctl" ;
if [[ $(command -v curl) ]]; then curl -L $RegUrl > "$ScriptWorkDir/regctl" ; chmod +x "$ScriptWorkDir/regctl" ; regbin="$ScriptWorkDir/regctl" ;
elif [[ $(command -v wget) ]]; then wget $RegUrl -O "$ScriptWorkDir/regctl" ; chmod +x "$ScriptWorkDir/regctl" ; regbin="$ScriptWorkDir/regctl" ;
else
printf "%s\n" "curl/wget not available - get regctl manually from the repo link, quitting."
fi
@@ -195,10 +196,10 @@ else
exit 1
fi
fi
### final check if binary is correct
# Final check if binary is correct
$regbin version &> /dev/null || { printf "%s\n" "regctl is not working - try to remove it and re-download it, exiting."; exit 1; }
### Check docker compose binary:
# Check docker compose binary
if docker compose version &> /dev/null ; then DockerBin="docker compose" ;
elif docker-compose -v &> /dev/null; then DockerBin="docker-compose" ;
elif docker -v &> /dev/null; then
@@ -209,7 +210,13 @@ else
exit 1
fi
### Numbered List -function:
# Check for jq binary
if [[ ! $(command -v jq) ]] ; then
printf "%s\n" "No jq binary, please install jq and try again, exiting."
exit 1
fi
# Numbered List function
options() {
num=1
for i in "${GotUpdates[@]}"; do
@@ -218,7 +225,7 @@ for i in "${GotUpdates[@]}"; do
done
}
### Listing typed exclusions:
# Listing typed exclusions
if [[ -n ${Excludes[*]} ]] ; then
printf "\n%bExcluding these names:%b\n" "$c_blue" "$c_reset"
printf "%s\n" "${Excludes[@]}"
@@ -226,11 +233,11 @@ if [[ -n ${Excludes[*]} ]] ; then
fi
# Variables for progress_bar function
DocCount=$(docker ps $Stopped --filter "name=$SearchName" --format '{{.Names}}' | wc -l)
ContCount=$(docker ps $Stopped --filter "name=$SearchName" --format '{{.Names}}' | wc -l)
RegCheckQue=0
### Testing and setting timeout binary
t_out=$(type -P "timeout")
# Testing and setting timeout binary
t_out=$(command -v timeout)
if [[ $t_out ]]; then
t_out=$(realpath $t_out 2>/dev/null || readlink -f $t_out)
if [[ $t_out =~ "busybox" ]]; then
@@ -240,16 +247,16 @@ if [[ $t_out ]]; then
else t_out=""
fi
### Check the image-hash of every running container VS the registry
# Check the image-hash of every running container VS the registry
for i in $(docker ps $Stopped --filter "name=$SearchName" --format '{{.Names}}') ; do
((RegCheckQue+=1))
progress_bar "$RegCheckQue" "$DocCount"
### Looping every item over the list of excluded names and skipping:
progress_bar "$RegCheckQue" "$ContCount"
# Looping every item over the list of excluded names and skipping
for e in "${Excludes[@]}" ; do [[ "$i" == "$e" ]] && continue 2 ; done
RepoUrl=$(docker inspect "$i" --format='{{.Config.Image}}')
LocalHash=$(docker image inspect "$RepoUrl" --format '{{.RepoDigests}}')
# Checking for errors while setting the variable:
if RegHash=$(${t_out} $regbin image digest --list "$RepoUrl" 2>&1) ; then
# Checking for errors while setting the variable
if RegHash=$(${t_out} $regbin -v error image digest --list "$RepoUrl" 2>&1) ; then
if [[ "$LocalHash" = *"$RegHash"* ]] ; then
NoUpdates+=("$i")
else
@@ -260,27 +267,27 @@ for i in $(docker ps $Stopped --filter "name=$SearchName" --format '{{.Names}}')
fi
fi
else
# Here the RegHash is the result of an error code.
# Here the RegHash is the result of an error code
GotErrors+=("$i - ${RegHash}")
fi
done
### Sort arrays alphabetically
# Sort arrays alphabetically
IFS=$'\n'
NoUpdates=($(sort <<<"${NoUpdates[*]}"))
GotUpdates=($(sort <<<"${GotUpdates[*]}"))
unset IFS
### Define how many updates are available
# Define how many updates are available
UpdCount="${#GotUpdates[@]}"
### List what containers got updates or not
# List what containers got updates or not
if [[ -n ${NoUpdates[*]} ]] ; then
printf "\n%bContainers on latest version:%b\n" "$c_green" "$c_reset"
printf "%s\n" "${NoUpdates[@]}"
fi
if [[ -n ${GotErrors[*]} ]] ; then
printf "\n%bContainers with errors, wont get updated:%b\n" "$c_red" "$c_reset"
printf "\n%bContainers with errors, won't get updated:%b\n" "$c_red" "$c_reset"
printf "%s\n" "${GotErrors[@]}"
printf "%binfo:%b 'unauthorized' often means not found in a public registry.\n" "$c_blue" "$c_reset"
fi
@@ -290,11 +297,11 @@ if [[ -n ${GotUpdates[*]} ]] ; then
[[ -n "$Notify" ]] && { [[ $(type -t send_notification) == function ]] && send_notification "${GotUpdates[@]}" || printf "Could not source notification function.\n" ; }
fi
### Optionally get updates if there's any
# Optionally get updates if there's any
if [ -n "$GotUpdates" ] ; then
if [ -z "$AutoUp" ] ; then
printf "\n%bChoose what containers to update.%b\n" "$c_teal" "$c_reset"
choosecontainers
printf "\n%bChoose what containers to update.%b\n" "$c_teal" "$c_reset"
choosecontainers
else
SelectedUpdates=( "${GotUpdates[@]}" )
fi
@@ -305,14 +312,23 @@ if [ -n "$GotUpdates" ] ; then
do
((CurrentQue+=1))
unset CompleteConfs
ContPath=$(docker inspect "$i" --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}')
ContConfigFile=$(docker inspect "$i" --format '{{ index .Config.Labels "com.docker.compose.project.config_files" }}')
ContName=$(docker inspect "$i" --format '{{ index .Config.Labels "com.docker.compose.service" }}')
ContEnv=$(docker inspect "$i" --format '{{index .Config.Labels "com.docker.compose.project.environment_file" }}')
# Extract labels and metadata
ContLabels=$(docker inspect "$i" --format '{{json .Config.Labels}}')
ContImage=$(docker inspect "$i" --format='{{.Config.Image}}')
ContUpdateLabel=$(docker inspect "$i" --format '{{ index .Config.Labels "mag37.dockcheck.update" }}')
ContRestartStack=$(docker inspect "$i" --format '{{ index .Config.Labels "mag37.dockcheck.restart-stack" }}')
### Checking if compose-values are empty - hence started with docker run:
ContPath=$(jq -r '."com.docker.compose.project.working_dir"' <<< "$ContLabels")
[ "$ContPath" == "null" ] && ContPath=""
ContConfigFile=$(jq -r '."com.docker.compose.project.config_files"' <<< "$ContLabels")
[ "$ContConfigFile" == "null" ] && ContConfigFile=""
ContName=$(jq -r '."com.docker.compose.service"' <<< "$ContLabels")
[ "$ContName" == "null" ] && ContName=""
ContEnv=$(jq -r '."com.docker.compose.project.environment_file"' <<< "$ContLabels")
[ "$ContEnv" == "null" ] && ContEnv=""
ContUpdateLabel=$(jq -r '."mag37.dockcheck.update"' <<< "$ContLabels")
[ "$ContUpdateLabel" == "null" ] && ContUpdateLabel=""
ContRestartStack=$(jq -r '."mag37.dockcheck.restart-stack"' <<< "$ContLabels")
[ "$ContRestartStack" == "null" ] && ContRestartStack=""
# Checking if compose-values are empty - hence started with docker run
if [ -z "$ContPath" ] ; then
if [ "$DRunUp" == "yes" ] ; then
docker pull "$ContImage"
@@ -322,7 +338,7 @@ if [ -n "$GotUpdates" ] ; then
fi
continue
fi
### cd to the compose-file directory to account for people who use relative volumes, eg - ${PWD}/data:data
# cd to the compose-file directory to account for people who use relative volumes
cd "$ContPath" || { echo "Path error - skipping $i" ; continue ; }
## Reformatting path + multi compose
if [[ $ContConfigFile = '/'* ]] ; then
@@ -331,12 +347,12 @@ if [ -n "$GotUpdates" ] ; then
CompleteConfs=$(for conf in ${ContConfigFile//,/ } ; do printf -- "-f %s/%s " "$ContPath" "$conf"; done)
fi
printf "\n%bNow updating (%s/%s): %b%s%b\n" "$c_teal" "$CurrentQue" "$NumberofUpdates" "$c_blue" "$i" "$c_reset"
### Checking if Label Only -option is set, and if container got the label
# Checking if Label Only -option is set, and if container got the label
[[ "$OnlyLabel" == true ]] && { [[ "$ContUpdateLabel" != true ]] && { echo "No update label, skipping." ; continue ; } }
docker pull "$ContImage"
### Check if the container got an environment file set and reformat it
# Check if the container got an environment file set and reformat it
if [ -n "$ContEnv" ]; then ContEnvs=$(for env in ${ContEnv//,/ } ; do printf -- "--env-file %s " "$env"; done) ; fi
### Check if the whole stack should be restarted
# Check if the whole stack should be restarted
if [[ "$ContRestartStack" == true ]] || [[ "$ForceRestartStacks" == true ]] ; then
$DockerBin ${CompleteConfs} stop ; $DockerBin ${CompleteConfs} ${ContEnvs} up -d
else

View File

@@ -2,12 +2,21 @@
SearchName="$1"
for i in $(docker ps --filter "name=$SearchName" --format '{{.Names}}') ; do
echo "------------ $i ------------"
ContPath=$(docker inspect "$i" --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}')
[ -z "$ContPath" ] && { "$i has no compose labels - skipping" ; continue ; }
ContConfigFile=$(docker inspect "$i" --format '{{ index .Config.Labels "com.docker.compose.project.config_files" }}')
ContName=$(docker inspect "$i" --format '{{ index .Config.Labels "com.docker.compose.service" }}')
ContEnv=$(docker inspect "$i" --format '{{index .Config.Labels "com.docker.compose.project.environment_file" }}')
ContLabels=$(docker inspect "$i" --format '{{json .Config.Labels}}')
ContImage=$(docker inspect "$i" --format='{{.Config.Image}}')
ContPath=$(jq -r '."com.docker.compose.project.working_dir"' <<< "$ContLabels")
[ "$ContPath" == "null" ] && ContPath=""
[ -z "$ContPath" ] && { "$i has no compose labels - skipping" ; continue ; }
ContConfigFile=$(jq -r '."com.docker.compose.project.config_files"' <<< "$ContLabels")
[ "$ContConfigFile" == "null" ] && ContConfigFile=""
ContName=$(jq -r '."com.docker.compose.service"' <<< "$ContLabels")
[ "$ContName" == "null" ] && ContName=""
ContEnv=$(jq -r '."com.docker.compose.project.environment_file"' <<< "$ContLabels")
[ "$ContEnv" == "null" ] && ContEnv=""
ContUpdateLabel=$(jq -r '."mag37.dockcheck.update"' <<< "$ContLabels")
[ "$ContUpdateLabel" == "null" ] && ContUpdateLabel=""
ContRestartStack=$(jq -r '."mag37.dockcheck.restart-stack"' <<< "$ContLabels")
[ "$ContRestartStack" == "null" ] && ContRestartStack=""
if [[ $ContConfigFile = '/'* ]] ; then
ComposeFile="$ContConfigFile"
@@ -20,6 +29,8 @@ for i in $(docker ps --filter "name=$SearchName" --format '{{.Names}}') ; do
echo -e "Compose files:\t\t$ComposeFile"
echo -e "Environment files:\t$ContEnv"
echo -e "Container image:\t$ContImage"
echo -e "Update label:\t$ContUpdateLabel"
echo -e "Restart Stack label:\t$ContRestartStack"
echo
echo "Mounts:"
docker inspect -f '{{ range .Mounts }}{{ .Source }}:{{ .Destination }}{{ printf "\n" }}{{ end }}' "$i"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 KiB

After

Width:  |  Height:  |  Size: 472 KiB

BIN
extras/example_old.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

View File

@@ -9,7 +9,7 @@
MSMTP=$(which msmtp)
SSMTP=$(which ssmtp)
if [ -n "$MSMPT" ] ; then
if [ -n "$MSMTP" ] ; then
MailPkg=$MSMTP
elif [ -n "$SSMTP" ] ; then
MailPkg=$SSMTP
@@ -18,8 +18,8 @@ else
fi
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
CfgFile="/usr/syno/etc/synosmtp.conf"
@@ -36,6 +36,8 @@ SenderMail=${SenderMail:-$(grep 'eventmail1' $CfgFile | sed -n 's/.*"\([^"]*\)".
printf "\nSending email notification.\n"
printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n\n$UpdToString"
$MailPkg $SendMailTo << __EOF
From: "$SenderName" <$SenderMail>
date:$(date -R)
@@ -44,10 +46,7 @@ Subject: $SubjectTag Updates available on $FromHost
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
The following containers on $FromHost have updates available:
$UpdToString
$MessageBody
From $SenderName
__EOF
}

View File

@@ -5,20 +5,15 @@
# Modify to fit your setup - if API, set AppriseURL to your Apprise ip/domain.
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
printf "\nSending Apprise notification\n"
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
read -d '\n' MessageBody << __EOF
Containers on $FromHost with updates available:
$UpdToString
__EOF
printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
apprise -vv -t "$MessageTitle" -b "$MessageBody" \

View File

@@ -0,0 +1,28 @@
### DISCLAIMER: This is a third party addition to dockcheck - best effort testing.
#
# Copy/rename this file to notify.sh to enable the notification snippet.
# Required receiving services must already be set up.
# Modify to fit your setup - set DiscordWebhookUrl
send_notification() {
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
echo "$UpdToString"
FromHost=$(hostname)
# platform specific notification code would go here
printf "\nSending Discord notification\n"
# Setting the MessageBody variable here.
MessageBody="🐋 Containers on $FromHost with updates available: \n$UpdToString"
# Modify to fit your setup:
DiscordWebhookUrl="PasteYourFullDiscordWebhookURL"
MsgBody="{\"username\":\"$FromHost\",\"content\":\"$MessageBody\"}"
curl -sS -o /dev/null --fail -X POST -H "Content-Type: application/json" -d "$MsgBody" "$DiscordWebhookUrl"
}

View File

@@ -4,11 +4,13 @@
# generic sample, the "Hello World" of notification addons
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
printf "\n%bGeneric notification addon:%b" "$c_green" "$c_reset"
printf "\nThe following docker containers on %s need to be updated:\n%s\n" "$FromHost" "$UpdToString"
printf "\nThe following docker containers on %s need to be updated:\n" "$FromHost"
printf "$UpdToString"
}

View File

@@ -5,8 +5,8 @@
# Modify to fit your setup - set GotifyUrl and GotifyToken.
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
@@ -14,7 +14,7 @@ send_notification() {
# Setting the MessageTitle and MessageBody variable here.
MessageTitle="${FromHost} - updates available."
MessageBody="Containers on ${FromHost} with updates available: ${UpdToString}"
printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
GotifyToken="Your Gotify token here"

View File

@@ -5,8 +5,8 @@
# Modify to fit your setup - set MatrixServer, Room_id and AccessToken
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here

View File

@@ -5,20 +5,15 @@
# Use your unique Topic Name in the URL below.
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
printf "\nSending ntfy.sh notification\n"
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
read -d '\n' MessageBody << __EOF
Containers on $FromHost with updates available:
$UpdToString
__EOF
printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
NtfyUrl="ntfy.sh/YourUniqueTopicName"

View File

@@ -6,8 +6,8 @@
# Modify to fit your setup - set Url and Token.
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
@@ -15,7 +15,7 @@ printf "\nSending pushbullet notification\n"
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
MessageBody="Containers on $FromHost with updates available: $UpdToString"
printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
PushUrl="https://api.pushbullet.com/v2/pushes"

View File

@@ -6,8 +6,8 @@
# Modify to fit your setup - set Url and Token.
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here
@@ -15,7 +15,7 @@ send_notification() {
MessageTitle="$FromHost - updates available."
# Setting the MessageBody variable here.
MessageBody="Containers on $FromHost with updates available: $UpdToString"
printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n$UpdToString"
# Modify to fit your setup:
PushoverUrl="https://api.pushover.net/1/messages.json"

View File

@@ -8,7 +8,7 @@
MSMTP=$(which msmtp)
SSMTP=$(which ssmtp)
if [ -n "$MSMPT" ] ; then
if [ -n "$MSMTP" ] ; then
MailPkg=$MSMTP
elif [ -n "$SSMTP" ] ; then
MailPkg=$SSMTP
@@ -17,8 +17,8 @@ else
fi
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# User variables:
@@ -28,6 +28,8 @@ SubjectTag="dockcheck"
printf "\nSending email notification.\n"
printf -v MessageBody "🐋 Containers on $FromHost with updates available:\n\n$UpdToString"
$MailPkg $SendMailTo << __EOF
From: "$FromHost" <$SendMailFrom>
date:$(date -R)
@@ -36,9 +38,7 @@ Subject: [$SubjectTag] Updates available on $FromHost
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
The following containers on $FromHost have updates available:
$UpdToString
$MessageBody
__EOF
}

View File

@@ -5,8 +5,8 @@
# Modify to fit your setup - set TelegramChatId and TelegramToken.
send_notification() {
Updates=("$@")
[ -s "$ScriptWorkDir"/urls.list ] && UpdToString=$( releasenotes ) || UpdToString=$( printf "%s\n" "${Updates[@]}" )
[ -s "$ScriptWorkDir"/urls.list ] && releasenotes || Updates=("$@")
UpdToString=$( printf '%s\\n' "${Updates[@]}" )
FromHost=$(hostname)
# platform specific notification code would go here

View File

@@ -6,3 +6,30 @@ apprise-api https://github.com/linuxserver/docker-apprise-api/releases
homer https://github.com/bastienwirtz/homer/releases
nginx https://github.com/docker-library/official-images/blob/master/library/nginx
vaultwarden-server https://github.com/dani-garcia/vaultwarden/releases
bruceforce-vaultwarden-backup https://github.com/Bruceforce/vaultwarden-backup/blob/main/CHANGELOG.md
actual_server https://actualbudget.org/blog
gotify https://github.com/gotify/server/releases
traefik https://github.com/traefik/traefik/releases
caddy https://github.com/caddyserver/caddy/releases
calibre https://github.com/linuxserver/docker-calibre/releases
calibre-web https://github.com/linuxserver/docker-calibre-web/releases
readarr https://github.com/Readarr/Readarr/releases
audiobookshelf https://github.com/advplyr/audiobookshelf/releases
gluetun https://github.com/qdm12/gluetun/releases
bazarr https://github.com/morpheus65535/bazarr/releases
bazarr-ls https://github.com/linuxserver/docker-bazarr/releases
prowlarr https://github.com/Prowlarr/Prowlarr/releases
prowlarr-ls https://github.com/linuxserver/docker-prowlarr/releases
recyclarr https://github.com/recyclarr/recyclarr/releases
sabnzbd https://github.com/linuxserver/docker-sabnzbd/releases
sonarr https://github.com/linuxserver/docker-sonarr/releases
radarr https://github.com/linuxserver/docker-radarr/releases
lidarr https://github.com/linuxserver/docker-lidarr/releases
jellyseerr https://github.com/Fallenbagel/jellyseerr/releases
jellyfin https://github.com/jellyfin/jellyfin/releases
home-assistant https://github.com/home-assistant/docker/releases
zigbee2mqtt https://github.com/Koenkk/zigbee2mqtt/releases
mqtt https://github.com/eclipse/mosquitto/tags