Keeping deployed application services aligned with upstream releases is a recurring maintenance challenge. When managing workloads defined in compose files or running on a local engine, teams frequently encounter silent configuration drift. A service might be pinned to a tag that receives security patches or bug fixes upstream, but unless someone manually queries the registry, those updates go unnoticed. Conversely, relying on mutable tags can introduce breaking changes when services are restarted or redeployed without prior validation.

Automating update detection often presents its own set of risks. Many automated utilities attempt to pull images and restart running workloads immediately upon detecting a new release. In mission-critical environments, an automatic restart triggered by an unvetted minor or major update can lead to unexpected downtime, configuration incompatibilities, or database schema migration issues.

The ideal operational pattern separates update discovery from deployment execution. This guide explains how to use imagenudge_container_update_notifier.py, an audit utility designed to inspect running services, compare semantic version tags, check remote registry manifests, and send alert notifications without modifying host state.

Install & Usage

The tool is packaged as a standalone Python script built entirely around standard library modules. It does not require installing external packages or configuring dedicated virtual environments.

To install the utility, download the single file, save it as imagenudge_container_update_notifier.py, and run it with Python:

python imagenudge_container_update_notifier.py --help 

You can execute the built-in offline test suite directly to confirm that version parsing and comparison routines execute correctly in your runtime environment:

python imagenudge_container_update_notifier.py 

Because the script uses built-in Python facilities for network requests, process calls, and system inspection, there are no dependencies to install via package managers.

How It Works

The script operates through modular components that parse image identifiers, compare version strings, interact with image registries, and format outgoing notifications.

Semantic Version Parsing and Comparison

To determine whether an upstream release represents an update, the script normalizes version tags using regular expressions. It strips leading prefix characters such as v or V and separates the string into major, minor, patch, and prerelease identifiers.

The parsing implementation is defined as follows:

def parse_semver(tag: str) -> Optional[Tuple[int, int, int, str]]: """Parse tag string into (major, minor, patch, prerelease).""" clean_tag = tag.lstrip("vV") pattern = r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([0-9A-Za-z.-]+))?$" match = re.match(pattern, clean_tag) if not match: return None major = int(match.group(1)) minor = int(match.group(2) or 0) patch = int(match.group(3) or 0) prerelease = match.group(4) or "" return (major, minor, patch, prerelease) 

Once parsed, the compare_semver function evaluates two version tuples sequentially:

  1. It compares the core numerical values (major, minor, patch). If the target version exceeds the current version, it registers as a forward release.
  2. If the numerical versions are identical, it inspects the prerelease string. A stable release is treated as newer than a prerelease build sharing the same numerical prefix.
  3. If both tags contain prerelease strings, they are compared lexicographically.

Workload Inspection and Digest Verification

The tool gathers running workload definitions from two potential sources:

  • Local Runtime Daemons: The script defines a custom HTTP connection class that communicates directly over a local UNIX domain socket. This interface sends standard HTTP requests to query active workloads and retrieve local image metadata without requiring external client packages.
  • Compose Files: The parse_compose_file function reads compose specifications directly, identifying services and their declared image references.

When inspecting an image reference, the script standardizes the identifier into an internal object containing the registry domain, repository name, tag, and optional digest.

To determine whether an image has received an update under the same tag, the script contacts the remote registry using an HTTP HEAD request against the manifest path. The client inspects the returned headers for the content digest header. If the registry demands authentication, the client intercepts authentication challenges, requests an access token using standard protocol parameters, and retries the request with the bearer token attached.

Dispatching Alerts

When a newer digest or semver progression is identified, the script formats an alert payload. Rather than executing changes locally, it routes notifications to operators through configurable alerting channels:

def send_notification( endpoint: str, subject: str, body: str, headers_dict: Optional[Dict[str, str]] = None, ) -> bool: """Send notification to webhook or ntfy/gotify compatible endpoint.""" if not endpoint: return False req_headers = { "User-Agent": "ImageNudge/1.0", "Content-Type": "application/json", } if headers_dict: req_headers.update(headers_dict) payload = json.dumps({"topic": "updates", "title": subject, "message": body}).encode("utf-8") req = urllib.request.Request(endpoint, data=payload, headers=req_headers, method="POST") try: with urllib.request.urlopen(req, timeout=10) as resp: return resp.status in (200, 201, 202, 204) except Exception as exc: sys.stderr.write(f"Failed sending notification to {endpoint}: {exc}\n") return False 

For environments relying on direct email reports, the script also includes an SMTP function using Python's standard email message library to transmit structured text summaries to specified administrative mailboxes.

Limitations

Understanding the technical boundaries of the code ensures proper integration into your maintenance workflow:

  • Compose Parsing Mechanism: The parse_compose_file function uses regular expression line matching rather than a full structured document parser. It assumes standard indentation and single-line image declarations. Complex specifications relying on anchors, dynamic template tags, or unusual formatting might fail to parse cleanly.
  • Authentication Protocol Support: The registry client specifically supports Bearer token authentication flows that supply realm, service, and scope challenges. Registries utilizing basic HTTP authentication, mutual TLS authentication, or custom vendor credential helpers are not supported by the client implementation.
  • Semantic Version Format Restrictions: Version parsing expects numeric strings formatted as major, minor, and patch sequences. Workloads tagged with Git commit hashes, Unix timestamps, calendar versions, or arbitrary descriptive tags cannot be compared with semantic arithmetic.
  • Passive Monitoring Only: The script does not modify deployment files, pull layers, or restart services. It serves strictly as an inspection and notification utility, leaving deployment execution to manual intervention or existing deployment pipelines.

Frequently Asked Questions

Does the script need elevated administrative privileges to run?

Access to the local runtime daemon requires read permissions on the corresponding UNIX domain socket file. If the executing user account does not possess read access to that socket, the daemon queries will fail gracefully, though compose file scanning will continue to operate normally.

Can the script detect updates if an image tag remains unchanged?

Yes. When a tag is updated upstream with a newly built revision, the image digest changes. The script queries the registry manifest for the latest digest header and flags a drift if it differs from the digest recorded in local runtime metadata.

How does the tool handle registries that require custom certificates?

The HTTP client leverages the operating system default certificate validation context via Python's standard SSL implementation. If private registries rely on private internal certificate authorities, those root certificates must be trusted at the operating system or Python environment level to prevent connection errors.

Full version and the rest of the toolkit: ImageNudge container update notifier on PyForge. Product page: https://py-forge.com/products/imagenudge-container-update-notifier