diff --git a/HatarashiHako b/HatarashiHako new file mode 100755 index 0000000..cca39e5 --- /dev/null +++ b/HatarashiHako @@ -0,0 +1,119 @@ +#!/bin/bash +##Script to update Docker container images occasionally and alert when update is done. +source /root/.bash_profile +if [[ $1 =~ "-v|--verbose|verbose" ]]; then + source /home/shmick/Scripts/Okiru "$1" +else + source /home/shmick/Scripts/Okiru +fi +source /etc/environment +#Remember where you are to change back to later +LOCAL_DIR=`pwd` +#This is where containers live +CONTAINER_DIR="/var/Red-Vol/Media/Containers/" +declare -a CONTAINER_PATHS +declare -a OUTDATED_CONTAINERS +declare -a FAILED_CONTAINERS +declare -a UPDATED_CONTAINERS +#Remove log from last runs, if present +if [[ -f /tmp/docker-updated ]]; then + rm /tmp/docker-updated +fi +#Start counting how many containers fail; appears in final mail subject. +OUTDATED_COUNT="0" +CONTAINER_PATHS=$(find $CONTAINER_DIR -maxdepth 2 -type f -name docker-compose.yml ! -path '*Archive*' | xargs dirname ) +#Find containers in ^ base dir ^ in base container path ^ by finding compose files ^ (not here) ^ and getting their directory name. +for container_path in ${CONTAINER_PATHS[@]}; do + cd $container_path + debug "Working on container directory $container_path" + container_stack=$(basename $container_path) + info "Working on stack" "$container_stack" + container_images="$(cat $container_path/docker-compose.yml | grep -E "image: ([a-z]+)/([a-z]+)(:[a-z0-9].*$)?" | grep -Ev 'postgresql|mariadb' | awk '{print $2}')" +# search for a pattern of something:something with optional :tag ^ avoid database containers print ^ image name + for container_image in $container_images; do + container_name="$(echo $container_image | awk -F/ '{print $2}' | sed "s/\:.*//")" +# remove everything after the : ^ + debug "$container_stack has image $container_image" + if [[ -n $(echo $container_image | grep -E "(.*:[a-z0-9].*$)") ]]; then +# check if there is a :tag present ^ + image_tag=":$(echo $container_image | awk -F: '{print $NF}')" +# !! Add : ^ before image !! so it is only added to later commands if there is an image at all + debug "$container_image has tag $image_tag" + export container_image=$(echo $container_image | awk -F: '{print $1}') +# If the container does have a tag, keep the base name ^ without it (before the :) + fi + debug "Fetching local image checksum with: docker inspect \"$container_image$image_tag\" | grep -Eo \"$container_image@sha256:([0-9a-zA-Z].*)(\")\" | sed -e 's/\"//g' | awk -F@ '{print \$2}" + local_image=$(docker inspect "$container_image$image_tag" | grep -Eo "$container_image@sha256:([0-9a-zA-Z].*)(\")" | sed -e 's/"//g' -e 's/\s+//g' | awk -F@ '{print $2}') +# remember, this bit ^ is empty without an image ^ this is the main image checksum remove ^ " and whitespace and^ get the checksum after the @ + if [[ -z $local_image ]]; then + error "Error fetching local image checksum for container $container_name!" + #The script will complain about failed containers later on + FAILED_CONTAINERS+=("(local) $container_name") + continue 2 + else + debug "Local SHA256 for $container_image is $local_image" + fi + debug "Fetching remote image with: skopeo inspect --creds \"dkd6:Vulthuryol569\" docker://docker.io/$container_image$image_tag | grep Digest | head -1 | grep -Eo 'sha256:([0-9a-zA-Z].*)(\")' | sed -e 's/\"//g'" + #Use Skopeo, a Red Hat tool, with my Docker Hub account to register the remote image checksum + remote_image=$(skopeo inspect --creds "dkd6:Vulthuryol569" docker://docker.io/$container_image$image_tag | grep Digest | head -1 | grep -Eo 'sha256:([0-9a-zA-Z].*)(")' | sed -e 's/"//g' -e 's/\s+//g' ) + #Sometimes; Docker hub hangs up; try again if you failed + if [[ -z $remote_image ]]; then + remote_image=$(skopeo inspect --creds "dkd6:Vulthuryol569" docker://docker.io/$container_image$image_tag | grep Digest | head -1 | grep -Eo 'sha256:([0-9a-zA-Z].*)(")' | sed -e 's/"//g') + fi + #Now, if you still don't have an image after the second try, something's fuckey. + if [[ -z $remote_image ]]; then + error "Error fetching remote image checksum for container $container_name!" + FAILED_CONTAINERS+=("(remote) $container_name") + continue 2 + else + debug "Remote SHA256 for $container_image is $remote_image" + fi + #If we have both checksums, compare them; they should be identical, or the container is outdated. + if [[ -n $local_image ]] && [[ -n $remote_image ]] && [[ "$local_image" =~ "$remote_image" ]]; then + ok "$container_name is up to date!" + else + warn "$container_name is out of date!" + info "Attempting to update $container_name" + if docker-compose pull $container_name; then + info "Pulled latest image for $container_name succesfully. Restarting..." + if docker-compose up -d --remove-orphans; then + ok "$container_stack has been updated sucessfully!" + UPDATED_CONTAINERS+=("($container_stack) $container_name") + else + error "Failed to update $container_name!" + FAILED_CONTAINERS+=("($container_stack|update) $container_name") + #Add to array for mail report + OUTDATED_CONTAINERS+=("($container_stack) $container_name") + export OUTDATED_COUNT=$(($OUTDATED_COUNT+1)) + fi + else + error "Failed to pull image for $container_name!" + FAILED_CONTAINERS+=("($container_stack|pull) $container_name") + #Add to array for mail report + OUTDATED_CONTAINERS+=("($container_stack) $container_name") + export OUTDATED_COUNT=$(($OUTDATED_COUNT+1)) + fi + fi + #If you found an image tag, reset it before moving on to another container + image_tag="" + done + cd $LOCAL_DIR +done +echo "All done!" +#Iterate over the arrays and output results to a file; if needed, it will be neatly mailed. +if [[ ${#OUTDATED_CONTAINERS[@]} != 0 ]] || [[ ${#FAILED_CONTAINERS[@]} != 0 ]] || [[ ${#UPDATED_CONTAINERS[@]} != 0 ]]; then + if [[ ${#UPDATED_CONTAINERS[@]} != 0 ]]; then + printf "The following containers have updated succefully:\n" > /tmp/docker-updated + printf "%s\n" "${UPDATED_CONTAINERS[@]}" >> /tmp/docker-updated + fi + if [[ ${#OUTDATED_CONTAINERS[@]} != 0 ]]; then + printf "The following containers are out of date:\n" >> /tmp/docker-updated + printf "%s\n" "${OUTDATED_CONTAINERS[@]}" >> /tmp/docker-updated + fi + if [[ ${#FAILED_CONTAINERS[@]} != 0 ]]; then + printf "The following containers failed the update process:\n" >> /tmp/docker-updated + printf "%s\n" "${FAILED_CONTAINERS[@]}" >> /tmp/docker-updated + fi + cat /tmp/docker-updated | mail -s "Docker containers update report - `date +"%B %d %Y"`" -r "Takahe@pukeko.xyz" matanhorovitz@protonmail.com + rm /tmp/docker-updated +fi