Nahaufnahme einer Person, die mit einem Tablet auf einer Decke sitzt.

TechWiese Blog

Docker Hub rate-limiting und Azure

25. Januar 2021

Portrait Bild von Nico Meisenzahl

Nico Meisenzahl

Portrait Bild von Robin-Manuel Thiel

Robin-Manuel Thiel

Dieser Blogbeitrag ist ein Repost und stammt im Original aus dem Know-how-Bereich von TechWiese, dessen Artikel in diesem Blog aufgegangen sind.

Bevor wir über die Auswirkungen des Docker Hub rate-liming auf Ihre Azure Ressourcen sprechen wollen, wir euch hierzu vorab ein paar grundlegende Informationen geben.

Docker Hub rate-limiting

Vor einigen Zeit hat Docker angekündigt ab dem 2. November Container Pull Limits auf dem Docker Hub einzuführen. Docker begründet diese Entscheidung damit, dass es Docker nur damit möglich ist den Service auch für Millionen weitere Entwickler bereitzustellen:

In determining why rate limits were necessary and how to apply them, we spent considerable time analyzing image downloads from Docker Hub. What we found confirmed that the vast majority of Docker users pulled images at a rate you would expect for normal workflows. However, there is an outsized impact from a small number of anonymous users. For example, roughly 30% of all downloads on Hub come from only 1% of our anonymous users.

Nach einer Analyse der Images und der Nutzung von Docker Hub hat sich Docker für folgende Limits entschieden:

  • Free Plan – anonyme Nutzer: 100 Pulls in 6 Stunden
  • Free Plan – angemeldete Nutzer: 200 Pulls in 6 Stunden
  • Pro Plan – keine Limitierungen
  • Team Plan – keine Limitierungen

Für Firmen mit mehr als 500 Accounts bietet der Docker Vertrieb weitere Optionen an.

Die Limits gelten hierbei nicht für das bereitgestellte Image, sondern den Nutzer der diese herunterlädt. Aktiv sind diese seit dem 2. November 2020, wurden aber nicht sofort forciert. Docker hat sich hierbei entscheiden die Limits langsam auszurollen. Seit dem 18. November sind die oben beschrieben Limits jedoch vollständig aktiv.

Für anonyme (nicht authentifizierte) Nutzer sind die Limits basierend auf der Source-IP begrenzt. Dies kann in großen Umgebungen und Firmen ein Problem darstellen, wenn sich mehrere Konsumenten eines Images hinter der selben IP Adresse befinden. Aber auch für PaaS Cloud-Services welche von mehreren Nutzern genutz werden.

Des weiteren stellt Docker ein Programm bereit bei dem sich Open-Source Projekte bewerben können um von den neuen Limits exkludiert zu werden. Solle Container Images können dann von den Nutzern weiterhin ohne Limits geladen werden.

Weitere Infos sind auf dem Docker Blog zu finden:

Sowie der Dokumentation:

Abschließend sei an dieser Stelle noch erwähnt, dass rate-limits und Quotas eine Best Practice für Cloud-Dienste sind und Docker bei Docker Hub in der Vergangenheit fast keine Einschränkungen hatte.

Einschätzung & Best Practises

In diesem Abschnitt wollen tiefer auf die einzelnen Bereiche und deren Lösungswege eingehen.

Grundlegend ist zu erwähnen, dass ein Docker Hub Pro und Teams Account wie schon beschrieben jegliche Limits aufhebt. Mit solch einem Account unterstützen Sie zudem Docker um Services wie den Docker Hub weiterhin für jeden zugänglich bereitzustellen.

Hinweis:Die Umstellung der Limits auf Docker Hub ist eine gute Gelegenheit, den Umgang mit sogenanntem "Public Content" im Projekt zu überdenken. So angenehm einfach das Konsumieren von Docker Hub auch sein mag, muss man sich im klaren sein, sehr viel Verantwortung und Kontrolle aus den Händen zu geben. GitHub, IBM, Google, Microsoft, Docker und VMWare sind sich in einem Blogpost zu dem Thema auf dem OCI Blog einig, dass öffentliche Images immer in einer eigenen Container Registry zwischengespeichert und von dort aus konsumiert werden sollten. Dazu unten mehr.

Betreffen mich die neuen Limits?

Das Docker Hub rate-limiting kann unvorbereitete Firmen und einzelne Nutzer in verschiedenen Bereichen treffen und Probleme verursachen. Folgende Teilbereiche sind hierbei zu betrachten.

Docker for Desktop

Eine containerized Inner-Loop ist beim täglichen Entwickeln nicht mehr wegzudenken. Hierbei kommt ein einziger Nutzer im Alltag wahrscheinlich nicht an die Limits. Greifen Sie, sowie Ihre Kollegen hierbei jedoch unangemeldet auf den Docker Hub zu zählt hierbei ihre Source-IP als Grundlage für die Limits. Hierbei reichen dann schon 100 Kollegen, von denen jeder innerhalb von 6 Stunden ein einziges Image herunterlädt.

Wenn sich hierbei jedoch jeder mit seinem Account authentifiziert greift das Limit für Sie allein. Zudem erhöht es sich auf 200 Pulls in 6 Stunden. Dies sollte für eine normale Nutzung ausreichen. Weiterhin ist es auch möglich eigene Images bereitzustellen oder eine Registry Mirror einzuführen (mehr Details unten).

CI/CD Pipelines

Auch bei CI/CD Pipelines können die neuen Limits Probleme verursachen. Bei Container Image Builds zum Beispiel. Die meisten Base Images (FROM) sind hierbei im Docker Hub gehosted. Je nachdem wie viele Container Image Builds ausgeführt werden oder, von wie vielen Teams die Build Agents genutzt werden, können hier während eines Arbeitstages einige Pulls entstehen.

Des weiteren können auch bei containerized Pipelines die Anzahl der Pulls überschritten werden. Bei containerized Pipelines wird jeder Pipeline Task in seinem eigenen, dafür konfigurierten, Container ausgeführt.

Grundlegend kommt es unteranderem auch darauf an, ob Build Agents geteilt oder skaliert werden. Dies kann die benötigten Pulls sehr stark beeinträchtigen.

Auch hierbei ist es zu empfehlen sich gegen den Docker Hub zu authentifizieren. Alternativ können eigene Images (die nicht auf auf den Huber Hub basieren) oder ein Container Registry Mirror Abhilfe schaffen.

Betrieb Ihrer Anwendung

Auch bei der Ausführung und dem Betrieb ihrer Anwendungen und Container gibt es durch die neuen Limits einiges zu beachten. Wenn Sie größere Umgebungen betreiben, die dynamisch skalieren, kann es während des Betriebs nötig sein Images neu herunterzuladen (auf neu hochskalierten Instanzen beispielsweise). Erreichen Sie hierbei ihr Docker Hub Limit wird Ihre Anwendung gegebenenfalls nicht mehr gestartet. Dies können Sie natürlich vermeiden. Auch hier stehen Ihnen verschiedene Möglichkeiten zur Verfügung. Je nachdem wie Sie Ihre Anwendung betreiben können Sie auch hier ihre Docker Hub Credentials hinterlegen, eigene Images nutzen oder einen Container Registry Mirror nutzen.

Was habe ich für Optionen?

Nachdem wir uns nun einen Überblick verschafft haben welche Stellen in unserem Application Lifecycle betroffen sein können, schauen wir uns die oben erwähnten Ansätze genauer an.

Docker Hub Pro/Team Account

Neben der Option, sich mit einem kostenlosen Docker Hub Account vor dem Pull zu authentifizieren, besteht natürlich auch die Möglichkeit, einen Pro oder Team Account zu erwerben. Hierbei würden die angesprochenen Limits entfallen und sie können den Docker Hub weiterhin ohne jegliche (und sogar mit weiteren) Features nutzen.

Einen Container Registry Mirror

Eine weitere Möglichkeit ist das Betreiben eines Container Registry Mirrors. Hierbei wird eine Anfrage nicht direkt an den Docker Hub geleitet, sondern erst der Registry Mirror angefragt. Ist das gewünschte Image oder ein Image Layer schon vorhanden, wird dieser direkt über den Mirror ausgeliefert.

Diese Funktion wird von einigen Container Registries unterstützt. Ein Beispiel wäre hier die Container Registry von Docker.

Wichtig ist, dass der Mirror auch entsprechend in der Container Runtime konfiguriert werden muss. Dies lässt sich bei den meisten Container Runtimes konfigurieren. Für den Docker Engine definieren Sie dies in der /etc/docker/daemon.json:

{
  "registry-mirrors": ["https://<my-docker-mirror-host>"]
}

Eigene Container Images

Wie schon angesprochen, ist es grundsätzlich auch anzuraten, die Nutzung von "Public Content" zu überdenken oder neu zu bewerten. Mit eigenen Container Images und einer eigenen Container Registry haben Sie Ihre Abhängigkeiten (in Bezug auf Container) in der eigenen Hand. Hierbei gibt es zwei Möglichkeiten: Zum einen können Sie bestehende Images in Ihre eigene Container Registry überführen und ausschließlich von dort für den Betrieb oder als Base-Image nutzen. Desweiteren können Sie auch Ihre eigenen Base-Images erstellen und über die eigene Container Registry bereitstellen.

Dies birgt natürlich auch Herausforderungen. In beiden Fällen nutzen Sie nicht mehr bereitgestellte und gewartete Container Images und müssen sich um das Ausrollen - z.B. neuer Security Fixes - selbst kümmern.

Auswirkungen auf die eigenen Umgebungen in Azure

Wie wirkt sich das Docker Hub rate-limiting auf Azure aus? Was sind die Best-Practises für die einzelnen Azure Ressourcen. Dies schauen wir uns in dem nächsten Abschnitt genauer an.

Azure PaaS Dieste wie App Services, Functions und Azure Container Instances

Für die meisten Azure PaaS Dienste, die auf Containern basieren, lassen sich Zugangsdaten für die genutzte Container Registry hinterlegen. Bei PaaS Diensten ist das besonders wichtig, da sich diese häufig die darunterliegende Host-Infrastruktur mit anderen teilen. Wenn die Pulls in Richtung Docker Hub aus PaaS Diensten heraus anonym erfolgen, kann es passieren, dass ein anderer Kunde, der zufällig auf der selben Infrastruktur läuft und gegenüber Docker Hub die gleiche IP Adresse hat, alle kostenfreien Rate Limits bereits aufgebraucht hat. Sobald ein Pull aber authentifiziert ist, werden die Limits auf Basis des jeweiligen Accounts und nicht der IP Adresse berechnet.

Wenn Sie sich entscheiden, trotz der Einschränkungen weiterhin Images von Docker Hub zu konsumieren, können Sie in Azure PaaS Diesten wie App Services, Functions und Azure Container Instances Zugangsdaten zu einem Docker Account hinterlegen. Hierzu muss der Zugangsmodus zu Docker Hub auf "Private" gestellt werden.

Screenshot des Azure Portals, in dem eine Azure Web App mit authentifiziertem Zugang zu Docker Hub erstellt wird

Screenshot des Azure Portals, in dem eine existierende Azure Web App mit authentifiziertem Zugang zu Docker Hub versehen wird

Sollten Sie sich entscheiden haben, in Zukunft auf eine eigene Container Registry (z.B. eine Azure Container Registry) zu setzen, kann diese im selben Menü hinterlegt werden.

Kubernetes

Für authentifizierte Requests gegen eine Container Registry aus einem Kubernetes Cluster heraus, existiert in Kubernetes das Pull Secret Konzept. Ein solches Secret kann beispielsweise mit dem folgenden Befehl über die Kommandozeile erstellt werden.

kubectl create secret docker-registry docker-hub \
  --docker-server=<your-registry-server> \
  --docker-username=<your-username> \
  --docker-password=<your-password> \
  --docker-email=<your-email>

Anschließend kann das Secret als imagePullSecret in der Pod definition referenziert werden.

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: <your-image>
  imagePullSecrets:
  - name: docker-hub

Zudem gibt es auch die Option das imagePullSecret über einen Service Account mehreren Workloads verfügbar zu machen.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
imagePullSecrets:
- name: docker-hub

Hierbei muss im Nachgang der Service Account der jeweiligen Ressource zugewiesen werden:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  serviceAccountName: my-app
  containers:
  - name: my-container
    image: <your-image>

Es gilt jedoch zu beachten, dass Secrets in Kubernetes an einen Namespace gebunden sind. Daher muss ein entsprechendes Pull Secret für jeden Namespace angelegt werden, aus dem heraus authentifizierte Anfragen gegen Docker Hub gestellt werden sollen.

Azure DevOps & GitHub Actions

Wie oben beschrieben kann auch Ihre CI/CD Pipeline betroffen sein.

Azure DevOps stellt einen Docker Login Task bereit um sich gegen den Docker Hub oder eine andere Container Registry zu authentifizieren. Der Login Task kann folgend in die Pipeline eingebunden werden:

- task: Docker@2
   displayName: Login to Docker Hub
   inputs:
    command: login
    containerRegistry: dockerHubConnection

Desweiteren müssen Sie die entsprechende Service Connections anlegen und Docker Hub auswählen.

GitHub hat für GitHub Actions laut diesem Issue auf GitHub ein Agreement mit Docker geschlossen. Genauere Informationen sowie eine Announcement gibt es hierzu noch nicht. Es ist davon aus auszugehen, dass das Agreement sich nur auf die shared Runner und nicht self-hosted Runner bezieht.

Um sich am Docker Hub anzumelden stellt Docker die Login Action zur Verfügung. Diese lässt sich folgend in den eigene GitHub Action Workflow integrieren:

- name: Login to Docker Hub
  uses: docker/login-action@v1
  with:
    username: ${{ secrets.DOCKERHUB_USERNAME }}
    password: ${{ secrets.DOCKERHUB_TOKEN }}

Tipps und Tricks aus der Community

Die Open-Source Community is auch schon aktiv. Untenstehend einige Blogbeträge und Projekte die bei der Implementierung von Lösungen und auch beim Monitoring der Limits helfen können:

  • Michael Friedrich von GitLab hat in einem Blog post zusammengefasst wie man die Limits über ein Monitoring Plugin sowie über einen Prometheus Exporter monitoren kann. Zum Blogpost geht es hier.
  • Alex Ellis hat das Open-Source Projekt registry-creds veröffentlicht das Verwalten von imagePullSecrets (für die Authentifizierung zum Docker Hub) in Kubernetes vereinfacht.
  • Google Cloud stellt einen Mirror des Docker Hubs zur Verfügung. Die Dokumentation ist hier zu finden.