Skip to content

Commit e530122

Browse files
committed
Add comprehensive Update Checking section to Docker Integration docs
- Document how Unraid's DockerUpdate class works (local vs remote SHA comparison) - Add update-status.json file structure and location - Show how to read and display SHA values for UI - Add section on handling pinned images with @sha256: digests - Include common update check issues troubleshooting table - Cross-reference pinned images from Image Name Normalization section
1 parent 3aabe0f commit e530122

1 file changed

Lines changed: 153 additions & 0 deletions

File tree

docs/advanced/docker-integration.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,155 @@ exec("docker rmi myimage:latest 2>&1", $output, $retval);
192192
?>
193193
```
194194

195+
## Update Checking
196+
197+
Unraid's Docker Manager provides a built-in system for checking if container images have updates available. This works by comparing the local image digest (SHA256 hash) with the remote registry's current digest for the same tag.
198+
199+
### How Unraid Update Checking Works
200+
201+
1. **Local digest**: Extracted from the image's `RepoDigests` field via `docker inspect`
202+
2. **Remote digest**: Fetched from the container registry's API (Docker Hub, GHCR, etc.)
203+
3. **Comparison**: If digests differ, an update is available
204+
205+
```php
206+
<?php
207+
require_once("/usr/local/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php");
208+
209+
$DockerUpdate = new DockerUpdate();
210+
$image = "library/nginx:latest";
211+
212+
// Force a fresh check (fetches from registry)
213+
$DockerUpdate->reloadUpdateStatus($image);
214+
215+
// Get the status: true = up-to-date, false = update available, null = unknown
216+
$status = $DockerUpdate->getUpdateStatus($image);
217+
218+
if ($status === null) {
219+
echo "Could not check for updates";
220+
} elseif ($status === true) {
221+
echo "Image is up-to-date";
222+
} else {
223+
echo "Update available!";
224+
}
225+
?>
226+
```
227+
228+
### Update Status Storage
229+
230+
Unraid stores update check results in a JSON file to avoid repeated registry queries:
231+
232+
```
233+
/var/lib/docker/unraid-update-status.json
234+
```
235+
236+
Structure:
237+
```json
238+
{
239+
"library/nginx:latest": {
240+
"local": "sha256:abc123...",
241+
"remote": "sha256:def456...",
242+
"status": "false"
243+
}
244+
}
245+
```
246+
247+
### Reading SHA Values
248+
249+
To display SHA digests in your UI (like showing which version will be updated):
250+
251+
```php
252+
<?php
253+
$dockerManPaths = [
254+
'update-status' => "/var/lib/docker/unraid-update-status.json"
255+
];
256+
257+
$updateStatusData = DockerUtil::loadJSON($dockerManPaths['update-status']);
258+
$image = "library/nginx:latest";
259+
260+
if (isset($updateStatusData[$image])) {
261+
$localSha = $updateStatusData[$image]['local'] ?? '';
262+
$remoteSha = $updateStatusData[$image]['remote'] ?? '';
263+
264+
// Shorten for display (first 12 chars after "sha256:")
265+
if ($localSha && strpos($localSha, 'sha256:') === 0) {
266+
$localSha = substr($localSha, 7, 12);
267+
}
268+
if ($remoteSha && strpos($remoteSha, 'sha256:') === 0) {
269+
$remoteSha = substr($remoteSha, 7, 12);
270+
}
271+
272+
echo "Local: $localSha → Remote: $remoteSha";
273+
}
274+
?>
275+
```
276+
277+
### Handling Pinned Images (SHA256 Digests)
278+
279+
Some users pin images to specific versions using SHA256 digests in their compose files:
280+
281+
```yaml
282+
services:
283+
redis:
284+
image: redis:6.2-alpine@sha256:abc123def456...
285+
```
286+
287+
These pinned images should **not** be checked for updates because:
288+
- The user explicitly wants that exact version
289+
- Registry checks return the latest tag digest, not the pinned digest
290+
- Comparing would always show a false "update available"
291+
292+
Detect and handle pinned images:
293+
294+
```php
295+
<?php
296+
/**
297+
* Check if an image is pinned with a SHA256 digest.
298+
* Returns array with image/digest info if pinned, false otherwise.
299+
*/
300+
function isImagePinned($image) {
301+
// Strip docker.io/ prefix first
302+
if (strpos($image, 'docker.io/') === 0) {
303+
$image = substr($image, 10);
304+
}
305+
306+
// Check for @sha256: digest suffix
307+
if (($digestPos = strpos($image, '@sha256:')) !== false) {
308+
$baseImage = substr($image, 0, $digestPos);
309+
$digest = substr($image, $digestPos + 1);
310+
return [
311+
'image' => $baseImage,
312+
'digest' => $digest,
313+
'shortDigest' => substr($digest, 7, 12) // First 12 chars
314+
];
315+
}
316+
317+
return false;
318+
}
319+
320+
// Usage
321+
$image = "docker.io/redis:6.2-alpine@sha256:abc123def456...";
322+
$pinned = isImagePinned($image);
323+
324+
if ($pinned) {
325+
// Show "pinned to abc123def456" instead of checking updates
326+
echo "Pinned to: " . $pinned['shortDigest'];
327+
} else {
328+
// Normal update check
329+
$DockerUpdate->reloadUpdateStatus($image);
330+
}
331+
?>
332+
```
333+
334+
### Common Update Check Issues
335+
336+
| Issue | Cause | Solution |
337+
|-------|-------|----------|
338+
| Always shows "update available" after pull | Cached local SHA is stale | Clear `local` field before `reloadUpdateStatus()` |
339+
| Image not found in status file | Image name format mismatch | Use `DockerUtil::ensureImageTag()` to normalize |
340+
| Pinned image shows "not checked" | `@sha256:` suffix confuses the check | Detect pinned images and skip update check |
341+
| Official images not matching | Missing `library/` prefix | `ensureImageTag()` adds it automatically |
342+
```
343+
195344
## Unraid Docker Integration
196345

197346
### Reading Docker Configuration
@@ -410,6 +559,10 @@ function normalizeImageForUpdateCheck($image) {
410559
?>
411560
```
412561

562+
{: .note }
563+
> Before normalizing, check if the image is pinned using `isImagePinned()` (see [Update Checking](#handling-pinned-images-sha256-digests)). Pinned images should display their pinned status rather than being checked for updates.
564+
```
565+
413566
### General Guidelines
414567
415568
- Cache container lists when appropriate

0 commit comments

Comments
 (0)