Why CI pipelines hit Docker Hub limits and how the GitLab dependency proxy helps
Pipelines that fail on image pulls from Docker Hub usually look like flaky builds rather than a platform problem. Jobs that start with a docker: or service image pull fail intermittently, runners in a shared pool hit the same anonymous or account-level pull limits, and retries only postpone the failure. The GitLab dependency proxy for container images is a pull-through cache that stores manifests and blobs, so after the first pull, later jobs in the same group can fetch the image from your GitLab instance instead of going back to Docker Hub. It is available in all tiers, including Free, and it is managed per group by group Owners. It is enabled by default, but it works at group level only, not per project, so teams should confirm the setting on the group that owns their CI projects before changing pipeline files.
Teams usually need it when several projects share runners, when autoscaling runners create many short-lived jobs, or when a pipeline pulls the same base images on every run. Before enabling it, confirm three things: which images your jobs reference and whether they are pulled through the proxy path, whether your runners can reach the GitLab instance on the network path the proxy requires, and how your administrators want the proxy controlled instance-wide. Confirm your exact limit and account setup with Docker, since the proxy does not change Docker Hub's own quotas for pulls it still has to make.
The dependency proxy does not replace a registry you operate for your own images, and it does not govern which upstream images are trusted. Images you build still belong in the GitLab container registry or another registry you control, and vetting base images is a separate control that the proxy does not provide. Plan for cache storage growth and cleanup, and keep the proxy under change control, because a group-level setting affects every pipeline in that group. The GitLab dependency proxy documentation is the place to confirm current configuration options and instance-wide controls for your version.
Who controls the dependency proxy at group and instance level
Group Owners are the people who manage the dependency proxy for container images on their own groups. The topic facts confirm that the proxy is managed per group by group Owners, that it is enabled by default, and that it is not available for projects. In practice, the group is the unit of control: the Owner decides whether the group's pipelines pull images through the cache, and the setting applies to the group rather than to individual repositories inside it.
- Enable or review the setting: Confirm the dependency proxy is on for each top-level group that runs CI jobs, since it is enabled by default and you should verify it has not been turned off.
- Scope by group, not project: Plan group boundaries with the proxy in mind, because projects cannot manage it on their own.
- Pair with CI variables: Pipelines must reference the proxy address, so Owners should coordinate with the teams that maintain
.gitlab-ci.ymlfiles. - Track who holds Owner rights: Limit the Owner role to people who should change image pull behavior for the whole group.
- Document the group setup: Record which groups use the proxy so that platform changes do not break pulls silently.
Before you rely on the cache, check the group's dependency proxy page and a test pipeline to confirm that the setting is active for the groups that need it.
Instance administrators run the self-managed GitLab installation and are responsible for the rules that apply across every group. The topic facts do not confirm which instance-wide controls exist for the dependency proxy, so this tab should be read as a list of questions to answer in the administration documentation for the version you run, not as a description of available switches. Administrators also own the platform underneath the proxy, including storage, network egress and the upgrade schedule.
- Confirm instance-wide options: Check the administration documentation for the installed version to see whether any instance-level setting governs the dependency proxy and what it changes.
- Plan storage and capacity: The proxy stores manifests and blobs, so confirm where that data lives and how it is backed up and cleaned up.
- Control outbound network access: Verify that the instance can reach the upstream registry and that egress rules match your network policy.
- Align with version upgrades: Check how dependency proxy behavior changes across the release cycle and plan around required upgrade stops.
- Review hardening guidance: Compare proxy settings with your instance hardening baseline before changing defaults.
Before you commit to a design, ask your implementation partner or the GitLab documentation for your exact version to confirm each instance-level option.
Platform and security teams usually decide whether the proxy is an approved path for image pulls in regulated environments. Group Owners can enable it for their groups, but the security team needs to decide whether that pull path fits the organization's supply chain policy. This tab focuses on governance: who approves the design, who reviews image sources, and how the decision is recorded for auditors.
- Define the approved pull path: Decide whether CI jobs must pull base images through the proxy and whether direct pulls from Docker Hub are still allowed.
- Set review ownership: Name the team that approves changes to group-level settings and the process for requesting them.
- Assess image provenance: A pull-through cache stores what the upstream registry serves, so pair it with your image scanning and approval process.
- Record decisions: Keep a written design note that states which groups use the proxy and why.
- Test access boundaries: Confirm that only intended groups and runners can reach the cache.
Before approving the design, ask for a written statement of what the instance and group settings control in your version.
Application teams are the people whose pipelines pull images, and they feel rate limit failures first. They do not usually control the proxy settings, but they decide how their .gitlab-ci.yml files reference images. Their role is to point jobs at the approved path and to report failures that suggest the cache is not being used. This tab covers what application teams should change in their own pipelines and what to escalate.
- Update image references: Change job images to the proxy path that the group Owner or platform team publishes.
- Check job logs: Confirm from the pipeline output which registry each job pulled from after the change.
- Avoid hardcoding credentials: Use the CI variables the platform provides rather than embedding tokens in files.
- Report pull failures: Escalate persistent errors to the group Owner rather than editing the setting yourself.
- Keep images current: Cached images still need to be updated when your base image tags change.
Before switching a pipeline, run it once on a branch and confirm the image path in the job output.
Configuration options and when each fits
This table compares the main ways a team can route Docker Hub pulls through GitLab, from enabling the group-level dependency proxy to leaving direct pulls in place. Read each row as a decision: when the option fits and what it costs you in administration or coverage. Most teams end up combining the proxy for high-volume base images with direct pulls for the rest.
| Option | When it fits | Trade-off |
|---|---|---|
| Group-level proxy enabled (default) | Groups whose CI jobs pull the same base images repeatedly from Docker Hub | Cached images must be managed by group Owners, and the cache sits inside the group boundary |
| Group-level proxy disabled | Groups with few pulls, or where all images must come from a source you approve separately | Every job pulls directly from Docker Hub, so rate limit hits remain possible |
| Proxy path in CI variables | Teams that want one setting per pipeline or runner group and can update variables centrally | Pipelines break if the variable is missing or points to the wrong group path |
| Proxy path in image references | Teams that want the cache path explicit in each Dockerfile or job image line | Every image reference must be edited, and reviewers must check the path on each change |
| Direct Docker Hub pulls for uncached images | Images not yet cached or outside the proxy's intended scope, such as one-off test images | Those pulls still count against Docker Hub limits, so confirm your current plan and limits with Docker |
| Proxy for projects | Not an option: the dependency proxy is managed per group, not per project | Plan project-level layouts around group membership instead |
Setting up the dependency proxy for CI jobs
This sequence turns the group-level dependency proxy into a pull-through cache that CI jobs use for Docker Hub images, and it confirms each stage works before the pipelines depend on it.
Confirm group structure and Owner access
Identify the top-level group that holds the projects whose pipelines pull Docker Hub images, and confirm that the person making changes holds the Owner role on that group. The dependency proxy is managed per group, so projects outside that group will not benefit from it. Check that membership reflects who should control the setting, and record the group path you will use in later steps. The step is complete when you can open the group's settings as an Owner and see the dependency proxy options.
Confirm the proxy is enabled for the group
The dependency proxy is enabled by default, but an earlier change or an instance-level control may have turned it off. Open the group's dependency proxy settings and confirm it is enabled. Also confirm with your administrators whether instance-wide settings restrict the feature for your environment. Verify by checking the setting's current state in the group, and note the proxy address the group displays so your CI configuration matches it exactly.
Decide which image references change
Inventory the
image:andservices:entries across the.gitlab-ci.ymlfiles and included templates in the projects that will use the proxy. Separate Docker Hub images that run in jobs from images pulled from other registries, since only the Docker Hub references are candidates for the proxy. Record which jobs pull the most images, because those are where rate limit failures usually show up. The output is a short list of files and job names to change, reviewed by the owners of those projects.Update CI job image references to the proxy
In each identified pipeline file, replace the Docker Hub image reference with the group's dependency proxy address and the matching image name and tag, using the predefined CI/CD variable or the literal address shown in the group settings. Confirm the exact variable name and image path syntax in the official dependency proxy documentation before editing, because the format determines whether the pull is cached. Make the change in a branch and open a merge request so reviewers can check it. The step is complete when the diff contains only intended image changes.
Ensure runners can authenticate to the proxy
Pulls through the dependency proxy require the job to authenticate, and the runner's executor must be able to reach the GitLab instance address that serves the proxy. Confirm with the runner administrator that the executor, whether shell, Docker or autoscaling, can resolve and reach the instance, and that the job token or credentials used for the pull are allowed by the group settings. Check the executor's Docker or container runtime configuration if pulls fail with authentication or certificate errors. The step is complete when a manual test pull from a runner host succeeds.
Run a test pipeline on a non-critical project
Trigger a pipeline on a low-risk project that uses one of the updated images, with a job that only pulls the image and runs a trivial command. Keep the job small so failures are easy to isolate. Watch the job log for the pull step and for the proxy address in the image reference. The output is a passing job whose log shows the image pulled from the group proxy rather than directly from Docker Hub.
Check cache hits and failures before wider rollout
Run the same test pipeline a second time and compare the pull output with the first run. A cache hit should show the image pulled without a fresh fetch from the upstream registry, which you can confirm in the job log and in the group's dependency proxy storage view. Review any failed pulls for authentication, network, or tag errors, and fix them before migrating other projects. Keep a record of the checks so the rollout can be repeated for additional groups. Confirm the exact log wording and storage view location in the official docs, since they can change between releases.
Security and operational considerations for the proxy cache
The dependency proxy sits between your CI jobs and Docker Hub, so it inherits decisions about who can pull, what gets cached and which upstream images are trusted. The cards below cover the controls to set and the signals to watch once the cache is in use.
Who can pull through the group proxy
The dependency proxy is managed per group by group Owners, so access follows group membership and the Runner credentials that CI jobs use. Confirm which groups can reach the proxy, who holds the Owner role for each group, and whether projects outside the intended group can pull through it. Review membership on the same schedule as your other group access reviews, since a broad group can expose the cache to more people than intended.
What the cache holds and who reads it
The proxy stores manifests and blobs for images that have been pulled through it, so cached content persists beyond the job that fetched it. Decide which groups need a proxy at all, and treat cached images as internal artifacts with the same visibility as the group that owns them. Ask whether your team needs a documented cleanup routine for cached content and confirm how that routine is run in your GitLab version.
Upstream image trust and digest pinning
A pull-through cache repeats whatever Docker Hub serves for a given tag, so a mutable tag such as latest can change under your pipelines. Pin base images by digest in Dockerfiles and CI configuration where reproducibility matters, and verify images against your own policy before they reach production. The proxy does not vet image contents, so image provenance remains your responsibility.
Keeping Runner and registry access consistent
CI jobs authenticate to the dependency proxy with GitLab's built-in variables, and Runners must be able to reach the GitLab instance and the proxy endpoint on the network you have designed. Confirm that Runner executors, including those on autoscaled hosts, resolve the same instance URL and trust the same certificate chain. Keep the proxy path separate from your container registry settings so that a change to one does not silently break the other.
Monitoring pull failures and rate limits
Pull failures in CI often appear as generic job errors, so decide where you will look for them before you need them. Watch job logs for failed manifest or blob requests, track which pipelines depend on Docker Hub, and record the upstream errors you see when rate limits are reached. Confirm with your Docker Hub account type and subscription how much pull capacity your organization has, because the proxy reduces repeated pulls but does not change the upstream limit itself.
Reviewing settings at each GitLab upgrade
Settings and behavior for container features can change between releases, so review the dependency proxy configuration whenever you move to a new GitLab version. Use the upgrade stops and the maintenance policy to plan the window, then check group settings, Runner versions and pull tests in a staging group. Keep Runner major and minor versions aligned with GitLab, as the Runner documentation advises, and record each review as part of your change evidence.
Questions teams ask before relying on the dependency proxy
Does the GitLab dependency proxy cost extra by tier?
No. The dependency proxy for container images is available in all GitLab tiers, so Free, Premium and Ultimate installations all get it. Your licensing decision should rest on other needs, such as advanced CI/CD and priority support on Premium, or security and compliance features on Ultimate. The proxy itself adds no line item. What you do pay for is the infrastructure that holds the cache, including storage for cached manifests and blobs and the network path from your runners to the instance. Ask your team to size that storage based on how many distinct images your pipelines pull and how long cached data should stay. Confirm the current tier matrix on the GitLab pricing page before purchase, since licensing terms can change.
Can individual projects use the dependency proxy?
No. The dependency proxy is managed at the group level, and it is not available for projects. Group Owners control it for their group, and pipelines in projects inside that group pull images through it. If your organization has many top-level groups, each one needs its own configuration and its own cache. Plan your group structure before rollout so that teams who share base images sit under the same group. Confirm with your administrators how groups map to teams, because moving projects between groups later changes which proxy they use.
How long does it take a platform team to set up the dependency proxy?
The feature is enabled by default, so the initial switch-on is short for an administrator who already runs a self-managed instance. The real duration depends on the work around it: updating .gitlab-ci.yml files or runner configuration to reference the proxy path, testing pulls from each runner type, and agreeing which base images teams should use. Those steps scale with the number of pipelines and groups involved. Ask any partner for a written estimate based on your group count, pipeline count and runner fleet, and ask what they will verify before handing over.
What does the work need from our internal staff?
Three groups of people need to be involved. Instance administrators confirm that the feature is enabled and review how it fits the instance-wide settings they control. Group Owners decide which groups use the proxy and who manages it there. Pipeline authors and platform engineers update image references and check that jobs pull successfully on your runners. Someone also needs to own the storage that holds cached data and watch its growth. Name these owners before work begins so that changes are not blocked by a missing approval or an unclear owner.
Can we set up the dependency proxy without a partner?
Yes, if your team already administers GitLab and runs its CI/CD infrastructure. The configuration is documented in the GitLab dependency proxy documentation, and no separate product needs to be purchased. A partner adds value when the rollout spans many groups, when runners sit in restricted networks, or when you want the change reviewed against your own hardening and change-control rules. DeployOpen plans, implements and documents self-hosted platforms in the client's own infrastructure, and most engagements are fixed-scope with the scope and deliverables agreed in writing before work starts. Decide based on your team's capacity and the number of groups in scope.
What drives the effort for a dependency proxy rollout up or down?
Effort rises with the number of groups, the number of pipelines that reference external images, and the variety of runner types and network paths in use. Air-gapped or tightly segmented networks add work because the proxy path must be reachable from every runner that needs it. Effort falls when you have a small group structure, consistent base image choices, and runners that already reach your instance. Ask for a quote that lists groups in scope, pipelines to be updated, runner types to be tested, storage sizing assumptions and the verification steps you will receive.
Does the dependency proxy keep working if the cache grows large?
The proxy stores manifests and blobs as a pull-through cache, so its footprint grows as teams pull more distinct images and versions. Plan storage capacity and decide how long cached data should remain, then monitor growth with your normal instance monitoring. Confirm how your installation's storage backend and cleanup behavior work before relying on the cache for critical pipelines, and test a restore or rebuild of the cache as part of your backup plan. Your administrators should check the GitLab Docs page on the dependency proxy for current behavior, since details can change between releases.
Limits to confirm in your environment before rollout
The dependency proxy is simple to switch on, but its benefit depends on how your Docker Hub account, Runners, network and storage behave. Each check below is something your team confirms in its own environment before CI jobs depend on the cache.
Docker Hub account and rate limits
Confirm which Docker Hub account and plan your Runners use when they pull images, and whether that account's limits apply to the pulls you expect. Pull the same images through the proxy and directly from Docker Hub during a test window, then compare the failure rates. If your jobs still hit limits on first pulls, the cache is not reducing the upstream traffic you assumed.
Air-gapped and offline behavior
Decide whether this instance has any route to Docker Hub at all. A pull-through cache only fills from its upstream, so in an offline environment you need a separate plan for getting base images into the instance and confirm with GitLab how the proxy behaves when the upstream is unreachable. Check this against GitLab's offline environment guidance before assuming the cache works as a standalone source.
Runner and network traffic
Verify that every Runner, including autoscaled or Kubernetes-based ones, can reach your GitLab instance and the proxy endpoint over the ports and hostnames your network policy allows. Check outbound rules, TLS trust for the instance certificate, and whether Runners need the proxy's URL injected through their configuration. A job that works on one Runner pool and fails on another usually points to a network or certificate gap.
Cache storage growth
The proxy stores manifests and blobs, so the cache grows with the number and variety of images your pipelines pull. Ask who owns the storage location, how it is sized, and whether cached content is removed or left to accumulate. Set a review date to look at actual growth and agree on who acts when storage nears its limit.
Behavior after upgrades
Confirm how the dependency proxy settings, group configuration and cached content carry through a GitLab upgrade, including the required upgrade stops. Test the proxy on a staging instance at the target version before you move production. Record the instance-wide setting your administrators rely on so you can check it again after each upgrade.
Scope beyond Docker Hub
The proxy covers container images pulled through GitLab's dependency proxy for the groups where it is enabled. It does not replace caching for other registries, package managers or images your pipelines pull from sources outside that path. List every registry your pipelines use today and decide, one by one, whether each is covered, bypassed or handled by another control.
When the dependency proxy is the right fix and when it is not
Use the group-level dependency proxy when Docker Hub rate limits cause repeated CI failures across several projects that share a GitLab group. The proxy sits between your runners and Docker Hub as a pull-through cache, so a base image pulled by one job can be served to later jobs from the group's cache instead of being fetched again from the public registry. That addresses the failure pattern directly: many pipelines, same handful of images, and jobs failing on pull. Before you commit, confirm the symptom in your own logs. Look for rate-limit errors on image pulls in failed jobs, and check whether they cluster in the same groups. If failures are rare or come from a single project, the cache changes little and the fix is probably elsewhere, such as in the job's own image choice or retry logic.
The proxy is not the right tool in every case. If you need images to be reproducible and approved, pinning base images by digest and referencing an internal registry, where you control which versions exist, is usually the stronger control. A mirror that you populate on a schedule, or a curated set of base images maintained by your platform team, suits environments where pulls must come only from approved sources, where you need to scan images before they reach developers, or where the build network cannot reach Docker Hub at all. Note that the dependency proxy caches what is pulled through it, so it does not by itself decide which images are trusted. The proxy is also managed per group by group Owners and is not available for projects, so a team that needs project-level control will need a different approach. Confirm with your GitLab administrators which groups will own the setting before you rely on it across the instance.
How DeployOpen works on this
DeployOpen treats the dependency proxy as one part of a wider GitLab deployment in your own infrastructure. We start from which pipelines pull which images, then set the group-level configuration, runner access and administrator controls to match how your teams work.
How we scope
- Inventory which groups and CI pipelines pull from Docker Hub and how often they hit rate limits today
- Confirm which GitLab tier and edition your instance runs, since the dependency proxy is available in all tiers
- Agree in writing which groups, runners and instance-wide administrator settings the engagement covers, as fixed-scope work
How we build
- Enable and configure the dependency proxy per group, with Owner permissions assigned to the people who will manage it
- Update CI jobs and runner network paths so image pulls resolve through the proxy, then test pipelines against it
- Review instance-wide enablement and storage placement, and test cache behavior with pulls, updates and cleanup
How we hand over
- Document the group configuration, pipeline changes, runner settings and the rollback steps for each group
- Record which administrator controls govern the proxy, who holds them and how changes are reviewed
- Walk your platform and CI teams through daily checks, so they can tell when cached images or pulls fail
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer after handover
- Retainers can cover GitLab version changes, so proxy behavior is rechecked alongside each upgrade
- Ask any provider to confirm how storage growth, cache cleanup and access reviews will be owned after go-live

