Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/model/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const schema = joi.object({
.object({
name: joi.string().min(1).required(),
url: joi.string().min(1).required(),
lookupImage: joi.string(),
})
.required(),
name: joi.string().min(1).required(),
Expand Down
1 change: 1 addition & 0 deletions app/prometheus/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ function init() {
'image_id',
'image_name',
'image_os',
'image_registry_lookup_image',
'image_registry_name',
'image_registry_url',
'image_tag_semver',
Expand Down
26 changes: 23 additions & 3 deletions app/watchers/providers/docker/Docker.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const {
wudDisplayIcon,
wudTriggerInclude,
wudTriggerExclude,
wudRegistryLookupImage,
} = require('./label');
const storeContainer = require('../../../store/container');
const log = require('../../../log');
Expand Down Expand Up @@ -112,15 +113,31 @@ function getTagCandidates(container, tags, logContainer) {

function normalizeContainer(container) {
const containerWithNormalizedImage = container;
const registryProvider = Object.values(getRegistries()).find((provider) =>
provider.match(container.image),
// Create a temporary image with parsed lookupImage if present for registry matching
let imageForMatching = container.image;
if (container.image.registry.lookupImage) {
const parsedLookupImage = parse(container.image.registry.lookupImage);
// If no domain specified, default to Docker Hub registry
const registryUrl = parsedLookupImage.domain || 'registry-1.docker.io';
imageForMatching = {
...container.image,
registry: {
...container.image.registry,
url: registryUrl,
},
name: parsedLookupImage.path,
};
}
const registries = getRegistries();
const registryProvider = Object.values(registries).find((provider) =>
provider.match(imageForMatching),
);
if (!registryProvider) {
log.warn(`${fullName(container)} - No Registry Provider found`);
containerWithNormalizedImage.image.registry.name = 'unknown';
} else {
containerWithNormalizedImage.image = registryProvider.normalizeImage(
container.image,
imageForMatching,
);
containerWithNormalizedImage.image.registry.name =
registryProvider.getId();
Expand Down Expand Up @@ -545,6 +562,7 @@ class Docker extends Component {
container.Labels[wudDisplayIcon],
container.Labels[wudTriggerInclude],
container.Labels[wudTriggerExclude],
container.Labels[wudRegistryLookupImage],
),
);
const containersWithImage = await Promise.all(containerPromises);
Expand Down Expand Up @@ -670,6 +688,7 @@ class Docker extends Component {
displayIcon,
triggerInclude,
triggerExclude,
wudRegistryLookupImageValue,
) {
const containerId = container.Id;

Expand Down Expand Up @@ -738,6 +757,7 @@ class Docker extends Component {
id: imageId,
registry: {
url: parsedImage.domain,
lookupImage: wudRegistryLookupImageValue,
},
name: parsedImage.path,
tag: {
Expand Down
5 changes: 5 additions & 0 deletions app/watchers/providers/docker/label.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,9 @@ module.exports = {
* Optional list of triggers to exclude
*/
wudTriggerExclude: 'wud.trigger.exclude',

/**
* Optional Lookup image (can be useful when pulling containers from a registry cache)
*/
wudRegistryLookupImage: 'wud.registry.lookup.image',
};
6 changes: 6 additions & 0 deletions docs/changelog/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Changelog

<<<<<<< HEAD
## 8.1.1
- :fire: [TELEGRAM] - Fix markdown character escape
=======
# 6.7.0 (wip)
- :star: [UI] - Add support for [Selfh.st](https://selfh.st/icons/) icons
- :star: [WATCHER] - Add support for alternative lookup registry url (useful when pulling from registry cache)
>>>>>>> ab7cf7c (:star: [WATCHER] - Add support for alternative lookup registry url (useful when pulling from registry cache))

## 8.1.0
- :star: Add 60s default jitter in docker watcher to avoid load spike on Docker Hub
Expand Down
32 changes: 30 additions & 2 deletions docs/configuration/watchers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,9 @@ To fine-tune the behaviour of WUD _per container_, you can add labels on them.
|-----------------------|:--------------:|----------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|
| `wud.display.icon` | :white_circle: | Custom display icon for the container | Valid [Material Design Icon](https://materialdesignicons.com/), [Fontawesome Icon](https://fontawesome.com/) or [Simple icon](https://simpleicons.org/) (see details below) | `mdi:docker` |
| `wud.display.name` | :white_circle: | Custom display name for the container | Valid String | Container name |
| `wud.link.template` | :white_circle: | Browsable link associated to the container version | JS string template with vars `${container}`, `${original}`, `${transformed}`, `${major}`, `${minor}`, `${patch}`, `${prerelease}` | |
| `wud.tag.exclude` | :white_circle: | Regex to exclude specific tags | Valid JavaScript Regex | |
| `wud.link.template` | :white_circle: | Browsable link associated to the container version | JS string template with vars `${container}`, `${original}`, `${transformed}`, `${major}`, `${minor}`, `${patch}`, `${prerelease}` | |
| `wud.registry.lookup.image` | :white_circle: | Alternative image to use for update lookups | Full image path (e.g., `namespace/image` or `registry.example.com/namespace/image`) | |
| `wud.tag.exclude` | :white_circle: | Regex to exclude specific tags | Valid JavaScript Regex | |
| `wud.tag.include` | :white_circle: | Regex to include specific tags only | Valid JavaScript Regex | |
| `wud.tag.transform` | :white_circle: | Transform function to apply to the tag | `$valid_regex => $valid_string_with_placeholders` (see below) | |
| `wud.trigger.exclude` | :white_circle: | Optional list of triggers to exclude | `$trigger_1_id,$trigger_2_id:$threshold` | |
Expand Down Expand Up @@ -437,3 +438,30 @@ docker run -d --name my_important_service --label 'wud.trigger.include=smtp.gmai
?> Threshold `minor` means that the trigger will run only if this is a `minor` or `patch` semver change

?> Threshold `patch` means that the trigger will run only if this is a `patch` semver change

### Use an alternative image for update lookups
When using a Docker Registry cache (Harbor, Nexus, etc.), you need to specify the upstream image that WUD should check for updates.

<!-- tabs:start -->
#### **Docker Compose**
```yaml
version: '3'

services:

traefik:
image: harbor.example.com/ghcr-proxy/traefik/traefik:v3.5.3
labels:
- wud.watch=true
- wud.registry.lookup.image=ghcr.io/traefik/traefik
```

#### **Docker**
```bash
docker run -d \
--name traefik \
--label 'wud.watch=true' \
--label 'wud.registry.lookup.image=ghcr.io/traefik/traefik' \
harbor.example.com/ghcr-proxy/traefik/traefik:v3.5.3
```
<!-- tabs:end -->
2 changes: 2 additions & 0 deletions e2e/features/api-container.feature
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ Feature: WUD Container API Exposure
And response body should be valid json
And response body path $.link should be https://github.com/home-assistant/core/releases/tag/2021.6.1
And response body path $.result.link should be https://github.com/home-assistant/core/releases/tag/2025.7.1
And response body path $.result.link should be https://github.com/home-assistant/core/releases/tag/2024.10.2
>>>>>>> ab7cf7c (:star: [WATCHER] - Add support for alternative lookup registry url (useful when pulling from registry cache))

Scenario: WUD must allow to trigger a watch on a container
Given I GET /api/containers
Expand Down
7 changes: 6 additions & 1 deletion ui/src/components/ContainerImage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,14 @@
<v-icon color="secondary">{{ registryIcon }}</v-icon>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title>Registry</v-list-item-title>
<v-list-item-title>Registry name</v-list-item-title>
<v-list-item-subtitle>{{ image.registry.name }}</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-content>
<v-list-item-title>Registry url</v-list-item-title>
<v-list-item-subtitle>{{ image.registry.url }}</v-list-item-subtitle>
<v-list-item-subtitle v-if="image.registry.lookupImage">{{ image.registry.lookupImage }} (lookup)</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-avatar>
Expand Down