Docker Hub Limits and Local Repos

Running this blog, and a number of other services, is a Docker Swarm. Its not kubernetes, but I don't need anything quite so... complex.

My use case is this: I've got multiple nodes, and multiple services. I'd like them to repeatably migrate and load balance themselves, provide a single entry point, and gracefully recover from failure when a node goes down for maintenance.

So far, its been working well. I write a docker-compose.yml, slap it on a manager node as a service, and we're off to the races. EXCEPT....

DockerHub now has a limit as to how much you can pull with a free account. Having other things to spend my money on, I chose to find another solution.

Docker themselves offer a container called a registry. I have that set up behind my usual infrastructure as a proxy (use this guide here:

What it DOESN'T tell you is two gotchas:

1) Traefik V2 requires some configuration to make it work.

2) Some images won't pull without a magic word. (Explained below)

So to solve #1, I've got the following labels on the registry entry in my compose file:

        traefik.enable: "true"
        traefik.http.routers.registry-insecure.entrypoints: web
        traefik.http.routers.registry.entrypoints: websecure
        traefik.http.routers.registry-insecure.rule: Host(``) && PathPrefix(`/v2`)
        traefik.http.routers.registry.rule: Host(``) && PathPrefix(`/v2`) 5000  
        traefik.http.middlewares.registry.redirectscheme.scheme: https
        traefik.frontend.passHostHeader: "true"
        traefik.http.routers.registry.tls.certresolver: dns-cloudflare
        traefik.http.routers.registry.tls: "true"

That should get you the proper load balancing you need on your Traefik V2 reverse proxy so you can access it (haven't tested externally yet).

Now, for the fun part. #2

I had some images that would pull and be cached just fine, "linuxserver/znc:latest" for example. But I had others, "mariadb:latest" for example, that wouldn't pull no matter what I did.

Finally I reached out and asked someone and found this tidbit, that I can't find anywhere in the docker documentation.

If no library name is given "library" should be used in its place.

So to pull mariadb:latest, you ACTUALLY have to pull "library/mariadb:latest"

Therefore, a valid proxy using docker-compose for mariadb looks like this:

version: '3.3'

      MYSQL_ROOT_PASSWORD: passw0rd!
      TZ: America/New_York
     - 3306:3306
     - default
      driver: json-file

I hope this saves someone some time in the future. Took me a few hours of poking around to find the answer.