Implement Container Virtual Registry cache miss scenario
🌱 Context
This is a continuation of the Container Virtual Registry implementation series:
-
Add Container Virtual Registry routes and stub ... (!210622 - merged)
✅ -
Modify Container Virtual Registry HandleFileReq... (!210719 - merged)
✅ - Implement Container Virtual Registry cache hit ... (!212712 - merged)
-
Implement pull cache miss scenario
👈 WE ARE HERE - Cleanup: DRY up duplicated code between
VirtualRegistries::ContainersControllerandGroups::DependencyProxy::ApplicationController
What does this MR do and why?
This commit implements the cache miss handling for Container Virtual Registry pull requests. When a requested image is not in cache, we:
- Proxy the download from upstream via Workhorse
- Create cache entry records for the image
- Stream the content to the Docker client
EE: true
References
🔬 How to set up and validate locally
🛠️ 1. Setup
Follow the same setup steps from !212712 (merged) to enable the feature flag and create a virtual registry with upstreams.
2. 🔓 Docker login to the virtual registry
docker login gdk.test:3000/virtual_registries/containers/<registry_id>
When the docker client asks for the password, paste a personal access token with read_virtual_registry permission.
3. 🔽 Docker pull from the virtual registry (cache miss)
Pull an image that is NOT in the cache:
# Pull an image from upstream (e.g., Docker Hub via the virtual registry)
docker pull gdk.test:3000/virtual_registries/containers/<registry_id>/library/alpine:latest
docker CLI automatically prepends library/ when pulling official images from DockerHub. But it does not do that for Virtual Registry. Hence, we have to add that to the URL ourselves: docker pull alpine => docker pull <gitlab-registry-url>/library/alpine
4. ✅ Verify the cache was populated
Check that cache entries were created:
registry = VirtualRegistries::Container::Registry.find(<registry_id>)
upstream = registry.upstreams.first
# Should show the manifest and blob entries that were cached
upstream.cache_entries.each do |entry|
puts "#{entry.relative_path} - #{entry.content_type} - #{entry.size} bytes"
end
5. ⚡ Verify cache hit on second pull
Pull the same image again - should be served from cache:
# This should be faster and served from cache
docker pull gdk.test:3000/virtual_registries/containers/<registry_id>/alpine:latest
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #549131