Regarding the latest changes with DockerHub, starting March 1 2025, the throttling limits for unauthenticated calls are reduced to 10 pulls per hour per IP address.
Internally, we use the following process to mitigate the DockerHub rate limits. In short, we first try to replace the image with an official or mirrored alternative. If that fails, we authenticate to DockerHub with a Pro account.
- Search for official alternatives of the image on
quay.io
,ghcr.io
,gcr.io
, ... - Search for a Verified Account mirror on
public.ecr.aws
- Check whether the
docker.io
(DockerHub) image is from a "Verified Publisher", as no rate limiting should apply according to the docs - Check whether you can pull the same image from
mirror.gcr.io
- Stay on
docker.io
(DockerHub) and use a Pro account withimagePullSecrets
(read further below)
Best way to keep using DockerHub is to authenticate and use your credentials (using a Docker Pro license).
The steps are:
-
Register on docker.com for a Pro/Team/Business plan depending on your needs
-
Create a new secret that includes your dockerhub credentials (upstream docs):
kubectl create secret docker-registry regcred --docker-server=https://index.docker.io/v1/ --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>
-
Ensure this secret is created in every namespace that needs to pull an image from the private registry.
-
In your container specification, you will use the following
imagePullSecret
upstream docs:spec: containers: - name: <your-container-name> image: <the-image-from-dockerhub> imagePullSecrets: - name: regcred # Or whatever you decided to name your secret from step 2
-
Congratulations, now you're authenticated to DockerHub
Alternatively, you can also do it via helm (upstream docs):
-
Have your credentials defined in your
values.yaml
:imageCredentials: registry: index.docker.io/v1/ username: someone password: sillyness email: [email protected]
-
Define our helper template as follows:
{{- define "imagePullSecret" }} {{- with .Values.imageCredentials }} {{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password .email (printf "%s:%s" .username .password | b64enc) | b64enc }} {{- end }} {{- end }}
-
Use the helper template in a larger template to create the
Secret
manifest:apiVersion: v1 kind: Secret metadata: name: regcred type: kubernetes.io/dockerconfigjson data: .dockerconfigjson: {{ template "imagePullSecret" . }}
-
Follow step 4 in the instructions above, to ensure your workload is using this
imagePullSecret
In the future, you can also consider to use ECR
Pull Through Cache, which makes you mitigate the authentication limits even further, by pulling once if an image has never been pulled before, and the consequent pulls will be coming from the cache, so it doesn't go over even to dockerhub.