Portfolio · Notes · Dotfiles

Search everything

Search case studies, engineering notes, and Dotfiles documentation.

    all case studies

    Case study 13

    Leaving Docker Hub without a flag day

    Registry mirrors and admission-time image rewrites let Kubernetes workloads move to our own registry before teams changed their manifests. The Docker Hub subscription was then retired.

    My role
    Proposed and implemented the migration, including pull-through caches, staged rewrite policies, manifest updates, and subscription retirement.
    Evidence
    The mirror served hundreds of images within weeks; the subscription was cancelled, and the rewrite rule remained as a fallback for old references.
    costreliabilitysecurity

    Remove the need for a coordinated switch

    Docker Hub pricing changes prompted a review of our dependency on the service. Hundreds of image references had accumulated across cluster manifests, CI, and developer workflows. Updating them all at once would have required coordination across many teams.

    I proposed and implemented a migration that separated traffic redirection from source cleanup. Workloads could begin pulling through our registry before their owners changed the manifests.

    Put a compatibility layer in front of the migration

    I created pull-through cache repositories in AWS ECR for Docker Hub, then extended the pattern to other public registries. Credentials were managed centrally, lifecycle rules controlled cache growth, and organization-wide read access made the mirrors available to consumers.

    Next I introduced Kyverno mutation policies that rewrite image references when Kubernetes admits a workload. A manifest can still name a Docker Hub image while the admitted pod uses the equivalent mirror path.

    EXHIBIT — THE INVISIBLE REGISTRY SWITCH
    Workload manifestimage: docker.io/library/nginx:1.27Kyverno mutation at admissionregistry rewritten in flightSafety netkept after the sweepPod pulls from the mirror111111111111.dkr.ecr.eu-west-1.amazonaws.com/docker-hub/library/nginx:1.27Docker Hubupstream cache fills and refreshes

    I rolled the policies out one namespace at a time. Teams continued deploying while image pulls moved through the mirror, which was serving hundreds of images within weeks. The cache configuration and rewrite policy are documented separately.

    The mirror serves cached content from our cloud account. Cache fills and refreshes still depend on the upstream registry, so this reduces direct dependency on Docker Hub during routine pulls without making upstream availability irrelevant.

    Finish the source migration without removing compatibility

    Once the mirror was handling traffic, I updated the manifests in a focused sweep. The rewrite policy remained enabled to catch references that had been missed or were introduced later.

    A year and a half later, the migration no longer needed its original explanatory note, so I removed that rationale from the policy document. The rule itself stayed: it continued to enforce the preferred registry path.

    What changed

    The Docker Hub subscription was cancelled. Image distribution gained centralized credentials and cache lifecycle rules, while Kubernetes workloads moved without a coordinated deployment freeze. The mirror layer also provided a distribution foundation for the internal image factory.