docker-registry-proxy is a pull-through cache for various container registries, primarily focused on docker images.

See also:

Getting this stood up took some trial and error, and very careful reading of the repository readme. Particular pain points:

  • Only the latest-debug image worked for me
  • Pay close attention in the HTTPS_PROXY environ – the URL is still plain HTTP, not HTTPS!
  • After setting up the proxy, run sudo docker system prune -a -f to clear all of Docker’s caches. Until then, I was getting errors that looked like DNS resolution.

Additionally, I had to set up custom DNS settings for this container. Add a volume to override the NGINX resolvers.conf:

docker-registry-proxy:
  container_name: docker_registry_proxy
  image: rpardini/docker-registry-proxy:latest-debug
  restart: unless-stopped
  ports:
    - 8012:3128
    # To enable debugging (DO NOT DO THIS IN PRODUCTION):
    # - 8013:8081  # Displays mitmproxy interface for incoming traffic
    # - 8014:8082  # Displays mitmproxy interface for outgoing traffic
  volumes:
    - /mnt/nas_pool/docker_reg/pullthru:/docker_mirror_cache
    - /opt/docker/docker-registry-proxy/ca:/ca
    - /opt/docker/docker-registry-proxy/nginx-resolver-conf:/etc/nginx/resolvers.conf
  environment:
    # Enable the pull-thru cache
    ENABLE_MANIFEST_CACHE: true
 
    # Max cache size
    CACHE_MAX_SIZE: 32g
 
    # Turned off while troubleshooting.  Does what it says on the tin.
    DISABLE_IPV6: true

and then in the /opt/docker/docker-registry-proxy/nginx-resolver-conf file:

resolver 192.168.30.142 ipv6=off;

I’m not sure if the semicolon is needed there, but it worked, so I haven’t touched it.

Client setup

It’s not trivial to set up a system to use this proxy, and although it’s all there in the README, it’s a little scattered.

  1. Create (if not already exists) /etc/systemd/system/docker.service.d
  2. Add a file in that directory; I’ll call it pullthru-cache.conf with the following. The trailing slash is important.
    [Service]
    Environment="HTTP_PROXY=http://<server>:<port>/"
    Environment="HTTPS_PROXY=http://<server>:<port>/"
    
  3. Pull down the CA certificate from the proxy server: curl http://<server>:<port>/ca.crt | sudo tee /usr/share/ca-certificates/docker-registry-proxy.crt
  4. Add the certificate to … some important config: sudo vim /etc/ca-certificates.conf and add /usr/share/ca-certificates/docker-registry-proxy.crt to the end of it
  5. Update certificates: sudo update-ca-certificates --fresh
  6. Reload systemd to include the new docker configs: sudo systemctl daemon-reload
  7. Restart docker to apply: sudo systemctl restart docker.service

At this point, it should be working. Test it by pulling an image, like sudo docker pull sphinxdoc/sphinx.

Recovering from failures

If the server breaks for any reason, this client will now be unable to pull docker images. This gets especially hairy when it’s the host running this proxy that’s now unable to pull images (say, to fix the problem). To bypass the proxy, comment out that systemd file, do a sudo systemctl daemon-reload, and then restart docker (sudo systemctl restart docker.service) and now pulling images will go straight to the real registry.

See also:

Clearing the cache

Sometimes, you may want to induce a clearing of the cache to fetch new images. I don’t know of an official way to do this, but you can simply go to the directory you mapped to docker_mirror_cache (per the above example, /mnt/nas_pool/docker_reg/pullthru) and delete all the contents therein. Then, run the typical docker update process.