If you're a platform engineer, you've probably had this conversation:"Security says we need to use hardened base images.""Great, where do I configure credentials for yet another registry?""Also, how do we make sure everyone actually uses them?"Or this one:"Why are our builds so slow?""We're pulling the same 500MB image from Docker Hub in every single job.""Can't we just cache these somewhere?"I've been working on Container Virtual Registry at GitLab specifically to solve these problems. It's a pull-through cache that sits in front of your upstream registries — Docker Hub, dhi.io (Docker Hardened Images), MCR, and Quay — and gives your teams a single endpoint to pull from. Images get cached on the first pull. Subsequent pulls come from the cache. Your developers don't need to know or care which upstream a particular image came from.This article shows you how to set up Container Virtual Registry, specifically with Docker Hardened Images in mind, since that's a combination that makes a lot of sense for teams concerned about security and not making their developers' lives harder.What problem are we actually solving?The Platform teams I usually talk to manage container images across three to five registries:Docker Hub for most base imagesdhi.io for Docker Hardened Images (security-conscious workloads)MCR for .NET and Azure toolingQuay.io for Red Hat ecosystem stuffInternal registries for proprietary imagesEach one has its own:Authentication mechanismNetwork latency characteristicsWay of organizing image pathsYour CI/CD configs end up littered with registry-specific logic. Credential management becomes a project unto itself. And every pipeline job pulls the same base images over the network, even though they haven't changed in weeks.Container Virtual Registry consolidates this. One registry URL. One authentication flow (GitLab's). Cached images are served from GitLab's infrastructure rather than traversing the internet each time.How it worksThe model is straightforward: Your pipeline pulls: