Files
nas-ops/nas-docker-pull
T
2026-06-03 17:49:07 +02:00

95 lines
3.5 KiB
Bash

#!/bin/bash
# nas-docker-pull — Pull Docker images and detect available updates
# Usage: nas-docker-pull
# Output: JSON (non-interactive mode) or colored text (terminal mode)
# Idempotent: as long as nas-docker-up has not recreated the containers,
# the container runs on the old image ID — the gap is always detected
# Also writes JSON to /tmp/nas-docker-pull.json for use by nas-update
set -euo pipefail
if [ -t 1 ]; then INTERACTIVE=true; else INTERACTIVE=false; fi
# Colors (terminal mode only)
if $INTERACTIVE; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
else
RED='' GREEN='' YELLOW='' CYAN='' BOLD='' RESET=''
fi
containers_json=""
count=0
if $INTERACTIVE; then
echo -e "${BOLD}--- Checking Docker images ---${RESET}"
fi
while IFS=: read -r container_id container_name; do
# Get compose_dir from container label
compose_dir=$(docker inspect --format='{{index .Config.Labels "com.docker.compose.project.working_dir"}}' "$container_id" 2>/dev/null | xargs)
# Skip containers not managed by compose
if [ -z "$compose_dir" ] || [ ! -d "$compose_dir" ]; then
continue
fi
image_name=$(docker inspect --format='{{.Config.Image}}' "$container_id")
old_image_id=$(docker inspect --format='{{.Image}}' "$container_id")
old_ver=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$container_id" 2>/dev/null || echo "")
[ -z "$old_ver" ] && old_ver="unknown"
if $INTERACTIVE; then
echo -ne " Checking ${CYAN}${container_name}${RESET}... "
fi
if ! docker pull "$image_name" > /dev/null 2>&1; then
if $INTERACTIVE; then echo -e "${YELLOW}⚠ Pull error (skipped)${RESET}"; fi
continue
fi
new_image_id=$(docker inspect --format='{{.Id}}' "$image_name" 2>/dev/null)
if [ "$old_image_id" != "$new_image_id" ]; then
new_ver=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$image_name" 2>/dev/null || echo "")
[ -z "$new_ver" ] && new_ver="available"
source_url=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.source"}}' "$image_name" 2>/dev/null | sed 's/\.git$//' || echo "")
if $INTERACTIVE; then
echo -e "${YELLOW}UPDATE AVAILABLE${RESET}: ${YELLOW}${old_ver}${RESET}${GREEN}${new_ver}${RESET}"
[ -n "$source_url" ] && echo -e " Source: ${CYAN}${source_url}${RESET}"
fi
entry="{\"name\":\"${container_name}\",\"image\":\"${image_name}\",\"compose_dir\":\"${compose_dir}\",\"current\":\"${old_ver}\",\"available\":\"${new_ver}\",\"source\":\"${source_url}\"}"
if [ $count -eq 0 ]; then
containers_json="${entry}"
else
containers_json="${containers_json},${entry}"
fi
count=$((count + 1))
else
if $INTERACTIVE; then echo -e "${GREEN}✅ Up to date${RESET}"; fi
fi
done < <(docker ps --format "{{.ID}}:{{.Names}}")
# Always write JSON to /tmp for use by nas-update
printf '{"count":%d,"containers":[%s]}\n' "$count" "$containers_json" > /tmp/nas-docker-pull.json
if $INTERACTIVE; then
echo ""
echo -e "${BOLD}--- Summary ---${RESET}"
if [ $count -eq 0 ]; then
echo -e "${GREEN}✅ All containers are up to date.${RESET}"
else
echo -e "${YELLOW}🐳 ${count} container(s) available for update.${RESET}"
fi
else
cat /tmp/nas-docker-pull.json
fi