November 2024 update: Learn about the upgraded Docker plans and choose the best Docker Subscription for you. Simpler, more value, better development and productivity.
Read our Docker Desktop release collection to learn about our latest enhancements and innovations.
—
Continuing with our move towards consumption-based limits, customers will see the new rate limits for Docker pulls of container images at each tier of Docker subscriptions starting from November 2, 2020.
Anonymous free users will be limited to 100 pulls per six hours, and authenticated free users will be limited to 200 pulls per six hours. Docker Pro and Team subscribers can pull container images from Docker Hub without restriction as long as the quantities are not excessive or abusive. Docker Pro and Team subscribers can pull container images from Docker Hub up to 50,000 pulls in a 24 hour period.
In this article, we’ll take a look at determining where you currently fall within the rate limiting policy using some command line tools.
Determining your current rate limit
Requests to Docker Hub now include rate limit information in the response headers for requests that count towards the limit. These are named as follows:
RateLimit-Limit
RateLimit-Remaining
The RateLimit-Limit
header contains the total number of pulls that can be performed within a six hour window. The RateLimit-Remaining
header contains the number of pulls remaining for the six hour rolling window.
Let’s take a look at these headers using the terminal. But before we can make a request to Docker Hub, we need to obtain a bearer token. We will then use this bearer token when we make requests to a specific image using curl.
Anonymous Requests
Let’s first take a look at finding our limit for anonymous requests.
The following command makes a request to auth.docker.io for an authentication token for the ratelimitpreview/test image and saves that token in an environment variable named TOKEN
. You’ll notice that we do not pass a username and password as we will for authenticated requests.
$ TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)
Now that we have a TOKEN
, we can decode it and take a look at what’s inside. We’ll use the jwt tool to do this. You can also paste your TOKEN
into the online tool located on jwt.io
$ jwt decode $TOKEN
Token header
------------
{
"typ": "JWT",
"alg": "RS256"
}
Token claims
------------
{
"access": [
{
"actions": [
"pull"
],
"name": "ratelimitpreview/test",
"parameters": {
"pull_limit": "100",
"pull_limit_interval": "21600"
},
"type": "repository"
}
],
...
}
Under the Token header
section, you see a pull_limit
and a pull_limit_interval
. These values are relative to you as an anonymous user and the image being requested. In the above example, we can see that the pull_limit
is set to 100 and the pull_limit_interval
is set to 21600 which is the number of seconds for the limit.
Now make a request for the test image, ratelimitpreview/test
, passing the TOKEN
from above.
$ curl --head -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest 2>&1 | grep RateLimit
< RateLimit-Limit: 100;w=21600
< RateLimit-Remaining: 96;w=21600
The output shows that our RateLimit-Limit
is set to 100 pulls every six hours – as we saw in the output of the JWT. We can also see that the RateLimit-Remaining
value tells us that we now have 96 remaining pulls for the six hour rolling window. If you were to perform this same curl command multiple times, you would observe the RateLimit-Remaining
value decrease.
Authenticated requests
For authenticated requests, we need to update our token to be one that is authenticated. Make sure you replace username:password
with your Docker ID and password in the command below.
$ TOKEN=$(curl --user 'username:password' "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)
Below is the decoded token we just retrieved.
$ jwt decode $TOKEN
Token header
------------
{
"typ": "JWT",
"alg": "RS256"
}
Token claims
------------
{
"access": [
{
"actions": [
"pull"
],
"name": "ratelimitpreview/test",
"parameters": {
"pull_limit": "200",
"pull_limit_interval": "21600"
},
"type": "repository"
}
],
...
}
The authenticated JWT contains the same fields as the anonymous JWT but now the pull_limit
value is set to 200 which is the limit for authenticated free users.
Let’s make a request for the ratelimitpreview/test
image using our authenticated token.
$ curl --head -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest 2>&1 | grep RateLimit
< RateLimit-Limit: 200;w=21600
< RateLimit-Remaining: 176;w=21600
You can see that our RateLimit-Limit
value has risen to 200 per six hours and our remaining pulls are at 176 for the next six hours. Just like with an anonymous request, If you were to perform this same curl command multiple times, you would observe the RateLimit-Remaining
value decrease.
Error messages
When you have reached your Docker pull rate limit, the resulting response will have a http status code of 429 and include the below message.
HTTP/1.1 429 Too Many Requests
Cache-Control: no-cache
Connection: close
Content-Type: application/json
{
"errors": [{
"code": "TOOMANYREQUESTS",
"message": "You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit"
}]
}
Conclusion
In this article we took a look at determining the number of image pulls allowed based on whether we are an authenticated user or anonymous user. Anonymous free users will be limited to 100 pulls per six hours, and authenticated free users will be limited to 200 pulls per six hours. If you would like to avoid rate limits completely, you can purchase or upgrade to a Pro or Team subscription: subscription details and upgrade information is available at https://docker.com/pricing.
For more information and common questions, please read our docs page and FAQ. And as always, please feel free to reach out to us on Twitter (@docker) or to me directly (@pmckee).
To get started using Docker, sign up for a free Docker account and take a look at our getting started guide.