agentleFS
abduznikabduznik/abduznik-skills/skills/docker-container-update-check/SKILL.md

docker-container-update-check

Skill2 starsChanged 2 months agoMITView on GitHub

Use when checking Docker containers for newer images.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 3 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Must NOT pull images or restart containers (a pure audit)

    line 20
  2. Distinctive:

    Run in parallel — a serial loop over 40+ containers times out (>420s):

    line 36
  3. Distinctive:

    UPDATE and one CURRENT confirms the parser is comparing real digests, not garbage.

    line 66

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Docker Container Update Check

When to Use

  • User asks "do any containers need updating?" on a Docker host (homelab, VPS, desktop)
  • Need a read-only update audit: which running containers have a newer image upstream
  • Must NOT pull images or restart containers (a pure audit)

Core Approach

Compare the digest the running container was created from (local RepoDigests) against the registry's current digest for the same tag (manifest inspect). No docker pull, no layer downloads, no container lifecycle impact.

# Per-container:
iid=$(docker inspect --format "{{.Image}}" "$c")          # image ID of running container
cur=$(docker image inspect --format "{{range .RepoDigests}}{{.}}{{end}}" "$iid" | sed "s/.*@//")
latest=$(docker manifest inspect --verbose "$img" | python3 -c "...parse digest...")
# cur == latest  -> CURRENT ; differ -> UPDATE

Run in parallel — a serial loop over 40+ containers times out (>420s):

docker ps -q | xargs -P 10 -I {} /tmp/check_container_updates.sh {}

Pitfalls

  • Cron Python scripts must pin Git's ssh.exe on exFAT drives: the target drive may be exFAT (no ACLs). Windows OpenSSH (C:\Windows\System32\OpenSSH\ssh.exe, first on system PATH) refuses any private key on exFAT/FAT with UNPROTECTED PRIVATE KEY FILE / permissions too open, while Git-bash's ssh works fine. A script that shells out to ssh by name → cron no_agent runs resolve to System32 OpenSSH → setup fails. Fix: SSH = r"C:/Program Files/Git/usr/bin/ssh.exe" and use [SSH, "-i", KEY, ...] in every subprocess call. Apply the same pattern to any watchdog script that needs ssh.
  • CRLF corrupts scripts deployed via SSH stdin: writing check_container_updates.sh through ssh host "cat > /tmp/..." from Windows adds \r, producing Syntax error: end of file unexpected (expecting "fi") and a SILENTLY BROKEN watchdog (all outputs empty). Fix on host: sed -i 's/\r$//' /tmp/check_container_updates.sh && bash -n ... — always verify with bash -n after deploy.
  • Multi-arch manifest shape: docker manifest inspect --verbose returns a LIST of per-platform descriptors for multi-arch images, but a DICT {"Descriptor": {...}} for single-arch images. A parser that only handles one shape mislabels every result of the other kind. Handle both: d[0]['Descriptor']['digest'] if list, d['Descriptor']['digest'] if dict.
  • Docker Hub anonymous rate limit: 100 pulls/6h per IP. When exhausted, manifest inspect fails with toomanyrequests: You have reached your unauthenticated pull rate limit and every docker.io image shows as CHECK_FAIL. ghcr.io and lscr.io are NOT affected — split results by registry to isolate the rate-limited ones, and re-check docker.io images after the window resets. A mass update the day before typically burns the quota.
  • latest-tag churn is normal: linuxserver-style images rebuild daily. Containers updated 23h ago can already show a newer digest. Report it, don't treat it as an alarm.
  • Per-image timeout: wrap manifest inspect in timeout 25 so one slow registry doesn't stall the batch.
  • Locally built images (no registry reference, e.g. python_stack-bingbong) and images with no RepoDigests show as CHECK_FAIL / DIGEST_UNKNOWN — they have no upstream to compare against; note them as "local build, update = rebuild".

Verification

  • Cross-check a couple of results: docker manifest inspect --verbose <img> for one UPDATE and one CURRENT confirms the parser is comparing real digests, not garbage.
  • unbound-style single-arch images are a good CURRENT control (dict shape path).

Support Files

  • scripts/check_container_updates.sh — the full per-container checker with the dual-shape parser baked in. Deploy to the host and run via xargs as above.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.