Brett Weir Dec 28, 2022 4 min read

Proxy Docker images via GitLab

Overcome Docker Hub rate limiting and improve resilience

Docker Hub rate limits container image pulls. These limits are easy to hit in a CI environment. This is especially likely if your CI environment is behind a NAT firewall. Thus, it is very important to enable a container proxy to ensure continuity of your CI service.

GitLab's Dependency Proxy feature allows you to proxy Docker Hub containers through GitLab.


It is highly recommended that you do NOT use GitLab's built-in dependency proxy variables directly. These are:





This is because, in doing so, you couple all CI code in every project you maintain to an implementation detail of GitLab that you do not have control over.

You also create a future requirement to update all existing projects if, for example, your company decides to host its own Docker Hub proxy, or move from GitLab Cloud to self-hosted, or any other reason that the registry URL might change.

So don't do that. The BrettOps container pipeline takes an alternative approach, and defines a layer of indirection for all of the above, as follows:

# registry

# registry with port number

# registry password

# registry username

Add a forward slash

You would think, and most documentation would suggest, that an appropriate way to use a container proxy is like so:


Not so fast! What happens if ${MY_PROXY} is not defined? This happens more often than you might think. You'll spend a good chunk of time setting up your CI pipeline to work perfectly with all the proxy variables tightly configured. In the meantime, you'll forget that once upon a time, you needed to build this image locally, and the next time you try doing this, you'll stumble over setting up the environment variables properly for a local build.

Nobody needs that. By adding a single forward slash to the variable value, you make it optional! At this point, building locally is no longer a problem.

This is why the container pipeline defines the CONTAINER_PROXY variable to equal the following default:


Log in to the registry

Before you can use the proxy registry to build new containers, you must authenticate. Don't spin cycles trying to debug a failing pipeline because you forgot to log in!

The following one-liner is the most succinct method I've found for Docker login in a CI pipeline.


This is much easier than trying to inject a complete config.json into a CI environment, as these commands can stack if you discover you need access to more registries:

echo "$CONTAINER_PROXY_2_PASSWORD" | docker login "$CONTAINER_PROXY_2_SERVER" -u "$CONTAINER_PROXY_2_USER" --password-stdin
# ...

Create a proxy group

GitLab declares the following two proxy registry variables:


  • CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX - The direct group that your project lives in.

Both of these are not ideal. If your organization has any kind of nesting in its GitLab group structure, you probably also have users that have direct access to some groups and not others, or users who have access to projects, but not to the groups that contain those projects.

GitLab users must have Guest privilege directly attached to a group to use the proxy registry of that group. This is an easy one to get bit by, so watch out.

Use the pipeline

The container pipeline is already configured to work the way that you expect. CONTAINER_PROXY is always defined when the pipeline is included, though it is still recommended to declare it globally in your GitLab group.