Skip to content

ci(build): route PR base-image pulls through mirror.gcr.io - #3042

Merged
Aleksei Sviridkin (lexfrei) merged 2 commits into
mainfrom
ray/build-dockerhub-mirror
Jun 26, 2026
Merged

Aleksei Sviridkin (lexfrei) merged 2 commits into
mainfrom
ray/build-dockerhub-mirror

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The Pull Request Build job authenticates only to the push registry (OCIR), so every base image (golang, ubuntu, alpine, nginx, …) is pulled from Docker Hub anonymously. Those pulls intermittently fail at auth.docker.io/token under Docker Hub's anonymous-pull rate limit, leaving the base image unresolved and failing make build — observed across several maintainer-branch runs in a short window.

Fix

Build the PR job on a docker-container buildx builder whose buildkitd routes docker.io through mirror.gcr.io (Google's public pull-through cache for Docker Hub: no auth, far higher limits, transparent fall-through to Docker Hub on a miss). This reuses the builder pattern already proven in build-main.yaml (same make build, same DOCKER_CONFIG auth forwarding); only the committed hack/buildkitd.toml mirror config is new. No base image versions or tags change.

Risk

Switches the PR build from the default embedded docker driver to a docker-container builder. build-main.yaml already runs the identical make build on that driver, so the path is exercised. The "Build Talos image" step uses docker run/skopeo (not buildx) and is unaffected.

Fallback

If mirror.gcr.io is unreachable, BuildKit logs trying next host and falls back to registry-1.docker.io, so the build still succeeds. Verified locally: a build pointed at a non-resolving mirror fell back to Docker Hub and exited 0 (at a small latency cost from the failed lookups). This strictly reduces build failures without adding a new hard dependency.

Coverage

Covered (the actual failure class — Docker Hub bases): ubuntu, golang*, alpine*, debian*, grafana/grafana, nginxinc/nginx-unprivileged, clickhouse/*, altinity/*, and explicit docker.io/library/*. Not covered, and never the problem: quay.io/*, gcr.io/distroless/static, ghcr.io/siderolabs/imager — the mirror is keyed to docker.io only, by design, and these were never subject to Docker Hub limits.

Optional follow-up (not in this PR)

The moby/buildkit builder image is still pulled from Docker Hub by the daemon to bootstrap the container builder (the mirror lives inside buildkit, so it cannot mirror its own bootstrap). That is one small pinned image versus dozens of base images, so this change is a strict net reduction in anonymous Docker Hub traffic. Pinning the bootstrap image through a mirror is deliberately left out: a no-fallback mirror on the bootstrap path would add risk for little gain.

Summary by CodeRabbit

  • Bug Fixes
    • Improved build reliability in pull request checks by using a configured container-based build setup.
    • Added a safer image-pull path for Docker Hub, with automatic fallback if the mirror is unavailable.
    • Preserved registry access during image builds so dependency and base-image fetching works more consistently.

The Pull Request Build job authenticates only to the push registry (OCIR),
so every base image (golang, ubuntu, alpine, nginx, ...) is pulled from
Docker Hub anonymously. Those pulls intermittently fail at
auth.docker.io/token under Docker Hub's anonymous-pull rate limit, leaving
the base image unresolved and failing make build.

Build on a docker-container buildx builder whose buildkitd routes docker.io
through mirror.gcr.io, Google's public pull-through cache for Docker Hub: no
auth, far higher limits, transparent fall-through to Docker Hub on a miss.
This reuses the builder pattern already proven in build-main.yaml (same
make build, same DOCKER_CONFIG auth forwarding); only the committed
hack/buildkitd.toml mirror config is new.

Fail-safe: if mirror.gcr.io is unreachable, BuildKit falls back to
registry-1.docker.io and the build still succeeds, so this strictly reduces
build failures without adding a new hard dependency.

Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
@github-actions github-actions Bot added area/build Issues or PRs related to image build infrastructure, multi-arch support size/M This PR changes 30-99 lines, ignoring generated files labels Jun 24, 2026
@coderabbitai

coderabbitai Bot commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The pull-request workflow now creates a docker-container buildx builder using hack/buildkitd.toml, which defines a Docker Hub mirror, and then runs make build with that builder while preserving the job’s Docker config.

Changes

CI buildx and BuildKit mirror

Layer / File(s) Summary
Builder setup and mirror config
.github/workflows/pull-requests.yaml, hack/buildkitd.toml
Adds a buildx setup step that uses hack/buildkitd.toml, and adds a BuildKit registry mirror for docker.io pointing to mirror.gcr.io.
Build step uses builder
.github/workflows/pull-requests.yaml
Passes the created buildx builder name into make build and keeps DOCKER_CONFIG set for the job-scoped Docker credentials.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • cozystack/cozystack#2962: Also updates CI workflow buildx setup and uses the per-run Docker config for builder authentication.

Suggested labels

kind/bug

Suggested reviewers

  • kvaps
  • lllamnyp
  • androndo

Poem

A bunny hopped through CI light,
With buildx set up just right.
A mirror gleamed near Docker’s door,
And builds fetched carrots evermore.
🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: routing PR base-image pulls through mirror.gcr.io for CI builds.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ray/build-dockerhub-mirror

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lexfrei
Aleksei Sviridkin (lexfrei) marked this pull request as ready for review June 25, 2026 14:44
@dosubot dosubot Bot added the area/ci Issues or PRs related to CI workflows, GitHub Actions, automation label Jun 25, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request improves CI build stability by routing base image pulls through Google's mirror.gcr.io. This mitigates intermittent build failures caused by Docker Hub's anonymous pull rate limits without introducing new hard dependencies, as the configuration includes a fail-safe fallback to the default registry.

Highlights

  • Build Reliability: Configured BuildKit to use mirror.gcr.io for docker.io image pulls to bypass Docker Hub anonymous rate limits.
  • Configuration: Added hack/buildkitd.toml to define registry mirror settings for CI buildx builders.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/pull-requests.yaml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds a BuildKit daemon configuration (hack/buildkitd.toml) to route Docker Hub base-image pulls through Google's public mirror (mirror.gcr.io) to avoid anonymous-pull rate limits in CI. The review feedback suggests updating the configuration comments to clarify that only official images are cached by this mirror, with others falling back to Docker Hub. Additionally, the commit scope in the PR title should be updated to comply with the repository's style guide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread hack/buildkitd.toml
Comment on lines +3 to +8
# Route docker.io base-image pulls through mirror.gcr.io, Google's public
# pull-through cache for Docker Hub. The Build job authenticates only to the
# push registry (OCIR), so every base image (golang, alpine, ubuntu, nginx, ...)
# is otherwise pulled from Docker Hub ANONYMOUSLY and is subject to Docker Hub's
# anonymous-pull rate limit -- which intermittently fails the build at
# auth.docker.io/token with the base image left unresolved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Note that mirror.gcr.io only mirrors official Docker Hub images (those in the library/ namespace, such as ubuntu, golang, alpine, nginx, etc.). Non-official/third-party images (such as grafana/grafana, nginxinc/nginx-unprivileged, clickhouse/*, and altinity/*) are not cached by mirror.gcr.io. For these images, BuildKit will transparently fall back to registry-1.docker.io, meaning they will still be pulled anonymously and remain subject to Docker Hub's rate limits.

It is recommended to update the comment in this file to reflect this limitation so future maintainers aren't confused if rate limit issues persist for non-official images.

Suggested change
# Route docker.io base-image pulls through mirror.gcr.io, Google's public
# pull-through cache for Docker Hub. The Build job authenticates only to the
# push registry (OCIR), so every base image (golang, alpine, ubuntu, nginx, ...)
# is otherwise pulled from Docker Hub ANONYMOUSLY and is subject to Docker Hub's
# anonymous-pull rate limit -- which intermittently fails the build at
# auth.docker.io/token with the base image left unresolved.
# Route docker.io base-image pulls through mirror.gcr.io, Google's public
# pull-through cache for Docker Hub. Note that mirror.gcr.io only caches
# official images (the library/ namespace, e.g., golang, alpine, ubuntu, nginx).
# Non-official images (e.g., grafana/grafana, clickhouse/*) are not cached and
# will fall back to registry-1.docker.io, remaining subject to rate limits.

Comment thread hack/buildkitd.toml
@@ -0,0 +1,21 @@
# BuildKit daemon config for CI builds.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

According to the repository style guide, the commit scope build in the PR title ci(build): ... is not a valid scope. Valid scopes under Meta are api, hack, tests, ci, and docs. Please update the PR title and commit message to use a valid scope, such as ci(ci) or ci(hack).

References
  1. Each commit must follow Conventional Commits format with a valid scope from the predefined list (e.g., ci, hack). (link)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
hack/buildkitd.toml (1)

20-21: 🚀 Performance & Scalability | 🔵 Trivial

Optional: add debug = true to verify mirror usage in logs.

Setting debug = true in buildkitd.toml exposes BuildKit daemon logs that explicitly confirm when mirror.gcr.io is used (e.g., via specific response headers). This is helpful for troubleshooting to ensure the registry fallback isn't being triggered unexpectedly.

🔍 Optional observability tweak
+debug = true
+
 [registry."docker.io"]
   mirrors = ["mirror.gcr.io"]
🤖 Prompt for 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.

In `@hack/buildkitd.toml` around lines 20 - 21, Add the optional BuildKit daemon
debug setting to the BuildKit config so mirror usage can be confirmed in logs;
update the existing buildkitd.toml registry configuration near the
[registry."docker.io"] block to include debug = true alongside the mirror
setting, keeping the change scoped to this BuildKit daemon config.
🤖 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.

Nitpick comments:
In `@hack/buildkitd.toml`:
- Around line 20-21: Add the optional BuildKit daemon debug setting to the
BuildKit config so mirror usage can be confirmed in logs; update the existing
buildkitd.toml registry configuration near the [registry."docker.io"] block to
include debug = true alongside the mirror setting, keeping the change scoped to
this BuildKit daemon config.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b9876708-2b1e-451c-ae41-d0e6912887e3

📥 Commits

Reviewing files that changed from the base of the PR and between 29bf56f and 7c519ad.

📒 Files selected for processing (2)
  • .github/workflows/pull-requests.yaml
  • hack/buildkitd.toml

@IvanHunters IvanHunters left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the diff. Scope cleanly limited to pull-requests.yaml + hack/buildkitd.toml, mirror only for docker.io, BuildKit falls back to upstream on miss. Final image digests unaffected (content-addressed, mirror serves bit-identical layers), so downstream consumers see identical manifests. Other registries (quay.io, ghcr.io, gcr.io) and private images are not touched. LGTM.

@lexfrei
Aleksei Sviridkin (lexfrei) merged commit 7ff0bf8 into main Jun 26, 2026
17 of 19 checks passed
@lexfrei
Aleksei Sviridkin (lexfrei) deleted the ray/build-dockerhub-mirror branch June 26, 2026 02:46
myasnikovdaniil added a commit that referenced this pull request Jun 26, 2026
Resolve conflict in .github/workflows/pull-requests.yaml: keep the new
per-package build matrix and fold in main's docker.io->mirror.gcr.io
base-image routing (#3042). Apply buildkitd-config: hack/buildkitd.toml
to all three new build legs (build, build-talos, finalize) so the mirror
fix covers the whole decomposed pipeline, not just the conflicted leg.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Myasnikov Daniil <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/build Issues or PRs related to image build infrastructure, multi-arch support area/ci Issues or PRs related to CI workflows, GitHub Actions, automation size/M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants