feat: add Docker registry mirror support for digest comparison - #1693
Conversation
- Resolve Docker daemon mirror configuration via Info() API - Build ordered endpoint list: per-registry mirrors, global mirrors, then canonical fallback - Thread mirror endpoints through GetToken, GetChallengeURL, CompareDigest, and fetchDigest - Add mirror resolution and endpoint building logic in pkg/container/mirror.go - Update all call sites and tests to pass optional endpoint parameter - Document registry mirror configuration and behavior in docs/advanced-features/registry-mirrors
…d clarify host override priority - Allow BuildManifestURL to accept full endpoint URLs (e.g. "https://mirror.example.com") as hostOverride, extracting host and scheme - Document host override priority in fetchDigest: redirect host, mirror endpoint, then canonical host - Clarify in manifest.BuildManifestURL that it always uses the canonical host and callers must apply overrides separately - Remove outdated comment about scheme usage in manifest.go
- Validate nil return for malformed image references - Test per-registry mirror fallback to global mirrors - Verify empty per-registry mirrors with no global fallback returns nil - Confirm mirror URLs with paths, queries, and fragments are preserved - Support IPv6 mirror addresses in endpoint construction
…estURL - Drop redundant "Empty string defaults to https" note since scheme behavior is now handled by caller
- Remove per-registry mirror support (IndexConfigs) from endpoint resolution - Drop container image parameter from buildMirrorEndpoints since registry-specific lookup is no longer needed - Update documentation to reflect global-only mirror configuration - Remove test cases covering per-registry mirror precedence and fallback behavior
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
WalkthroughAdds mirror-aware digest comparison: Watchtower discovers Docker daemon registry mirrors, builds ordered endpoints (mirrors then canonical), passes endpoints through auth and digest paths to try mirrors for digest fetches, and documents configuration with tests covering discovery, endpoint building, and fallback behavior. ChangesDocker Registry Mirrors Support
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## main #1693 +/- ##
==========================================
- Coverage 74.79% 74.69% -0.10%
==========================================
Files 59 60 +1
Lines 9949 10037 +88
==========================================
+ Hits 7441 7497 +56
- Misses 2243 2272 +29
- Partials 265 268 +3
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| Complexity | 1 medium |
🟢 Metrics 26 complexity · 11 duplication
Metric Results Complexity 26 Duplication 11
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/container/image_test.go`:
- Around line 197-200: The test currently only asserts that i.PullImage(...)
returned an error, which allows any failure to pass; instead assert the specific
pull-stage error ErrPullImageUnauthorized to confirm the fallback canonical pull
path was exercised. Replace the generic
gomega.Expect(err).To(gomega.HaveOccurred()) for the i.PullImage calls (the ones
using pullContainer, WarnAuto, types.UpdateParams{}) with an assertion that err
equals ErrPullImageUnauthorized (use the package error symbol
ErrPullImageUnauthorized), and make the same change for the other mirror test
block referenced (the similar i.PullImage call around lines 223–228).
In `@pkg/container/mirror.go`:
- Around line 47-49: The debug log currently emits raw mirror endpoints via
logrus.WithFields using info.Info.RegistryConfig.Mirrors, which can leak
userinfo; update the logging to sanitize each mirror URL before logging by
parsing each mirror string (use net/url.Parse) and replacing it with the host
(u.Host) or, if parsing fails, a redacted form without userinfo; then pass the
sanitized slice into logrus.WithFields instead of the raw
info.Info.RegistryConfig.Mirrors so the log only contains host-only values.
Reference the log call (logrus.WithFields) and the mirrors value
(info.Info.RegistryConfig.Mirrors) when making the change.
In `@pkg/registry/auth/auth.go`:
- Around line 418-422: The log call is currently writing the raw endpoint
(variable endpoint) which may include embedded credentials; parse the endpoint
string (e.g., using url.Parse) and log a sanitized value such as u.Host (or
u.Scheme + "://" + u.Host) instead of the original endpoint, falling back to a
redacted placeholder if parsing fails; update the logrus.WithFields call that
currently uses "mirrors": endpoint to use the sanitizedEndpoint and ensure any
u.User information is not logged.
In `@pkg/registry/digest/digest.go`:
- Around line 353-356: The code currently attaches the raw endpoint string to
epFields["registry_endpoint"], which can leak URL userinfo; update the logic
that builds epFields (epFields, endpoint) to parse endpoint with url.Parse and
store only the host portion (u.Host or u.Hostname()+":"+u.Port if port present)
or a safe fallback when parsing fails, so logs contain the hostname:port only
and never userinfo; preserve the existing empty-endpoint check and use the
sanitized host value when setting "registry_endpoint".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 539ecdf0-aba6-424e-9571-a1e4313c775a
📒 Files selected for processing (14)
build/mkdocs/mkdocs.yamldocs/advanced-features/registry-mirrors/index.mdpkg/container/cooldown_test.gopkg/container/image.gopkg/container/image_test.gopkg/container/mirror.gopkg/container/mirror_test.gopkg/registry/age.gopkg/registry/auth/auth.gopkg/registry/auth/auth_benchmark_test.gopkg/registry/auth/auth_test.gopkg/registry/digest/digest.gopkg/registry/digest/digest_integration_test.gopkg/registry/manifest/manifest.go
…al leakage - Parse and redact full URLs in mirror resolution, auth challenge, and digest fetch logging - Replace raw endpoint strings with host-only or `<redacted>` placeholders in log output - Update test assertions to verify specific `ErrPullImageUnauthorized` error type instead of generic occurrence check
|
Actionable comments posted: 0 |
Add Docker registry mirror support for digest comparison to enable update checks when primary registries are inaccessible.
Problem
Watchtower was not using the Docker daemon's configured
registry-mirrorswhen comparing image digests. Users in regions with restricted access to Docker Hub could not detect available updates.Solution
Watchtower now fetches the global
registry-mirrorsconfiguration from the Docker daemon and tries each mirror in order before falling back to the canonical registry host.Changes
Summary by CodeRabbit
New Features
Documentation