From e90d203fc01b62287f25007a8f8aad803484d578 Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Mon, 23 Mar 2020 10:07:19 +0100 Subject: [PATCH] Follow redirects and cache them properly --- Makefile | 21 +++++++++++++++++++++ nginx.conf | 52 ++++++++++++++++------------------------------------ 2 files changed, 37 insertions(+), 36 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7163d58 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +clean: + rm -rf docker_mirror_cache/* + +build: + docker build --tag docker-registry-proxy . + +start: + docker run --rm --name=docker-registry-proxy -it \ + -p 0.0.0.0:3128:3128 \ + -p 0.0.0.0:8081:8081 \ + -e DEBUG=true \ + -v $(dir $(abspath $(firstword $(MAKEFILE_LIST))))/docker_mirror_cache:/docker_mirror_cache \ + -v $(dir $(abspath $(firstword $(MAKEFILE_LIST))))/docker_mirror_certs:/ca \ + docker-registry-proxy + +stop: + docker stop docker-registry-proxy + +test: build start + +.INTERMEDIATE: clean stop diff --git a/nginx.conf b/nginx.conf index d526c75..6033aae 100644 --- a/nginx.conf +++ b/nginx.conf @@ -198,8 +198,8 @@ echo "Docker configured with HTTPS_PROXY=$scheme://$http_host/" proxy_cache_lock on; proxy_cache_lock_timeout 880s; - # Cache all 200, 301, 302, and 307 (emitted by private registries) for 60 days. - proxy_cache_valid 200 301 302 307 60d; + # Cache all 200, 206 for 60 days. + proxy_cache_valid 200 206 60d; # Some extra settings to maximize cache hits and efficiency proxy_force_ranges on; @@ -225,47 +225,28 @@ echo "Docker configured with HTTPS_PROXY=$scheme://$http_host/" return 405 "docker-registry-proxy: docker is trying to use v1 API. Either the image does not exist upstream, or you need to configure docker-registry-proxy to authenticate against $host"; } - # for the /v2/..../blobs/.... URIs, do cache, and treat redirects. location ~ ^/v2/(.*)/blobs/ { proxy_pass https://$targetHost; proxy_cache cache; - add_header X-Docker-Caching-Proxy-Debug-Cache "yes:blobs"; - - # Handling of redirects. - # Many registries (eg, quay.io, or k8s.gcr.io) emit a Location redirect - # pointing to something like cloudfront, or google storage. - # We hack into the response, extracting the host and URI parts, injecting them into a URL that points back to us - # That gives us a chance to intercept and cache those, which are the actual multi-megabyte blobs we originally wanted to cache. - # We to it twice, one for http and another for https. - proxy_redirect ~^https://([^:/]+)(/.+)$ https://docker.caching.proxy.internal/forcecachesecure/$1/originalwas$2; - proxy_redirect ~^http://([^:/]+)(/.+)$ http://docker.caching.proxy.internal/forcecacheinsecure/$1/originalwas$2; + proxy_cache_key $uri; + proxy_intercept_errors on; + error_page 301 302 307 = @handle_redirects; } + location @handle_redirects { + #store the current state of the world so we can reuse it in a minute + # We need to capture these values now, because as soon as we invoke + # the proxy_* directives, these will disappear + set $original_uri $uri; + set $orig_loc $upstream_http_location; - # handling for the redirect case explained above, with https. - # The $realHost and $realPath variables come from a map defined at the top of this file. - location /forcecachesecure { - proxy_pass https://$realHost$realPath; + # nginx goes to fetch the value from the upstream Location header + proxy_pass $orig_loc; proxy_cache cache; - - # Change the cache key, so that we can cache signed S3 requests and such. Only host and path are considered. - proxy_cache_key $proxy_host$uri; - - add_header X-Docker-Caching-Proxy-Debug-Cache "yes:forcecachesecure"; - - } - - # handling for the redirect case explained above, with http. - # The $realHost and $realPath variables come from a map defined at the top of this file. - location /forcecacheinsecure { - proxy_pass http://$realHost$realPath; - proxy_cache cache; - - # Change the cache key, so that we can cache signed S3 requests and such. Only host and path are considered. - proxy_cache_key $proxy_host$uri; - - add_header X-Docker-Caching-Proxy-Debug-Cache "yes:forcecacheinsecure"; + # But we store the result with the cache key of the original request URI + # so that future clients don't need to follow the redirect too + proxy_cache_key $original_uri; } # by default, dont cache anything. @@ -274,6 +255,5 @@ echo "Docker configured with HTTPS_PROXY=$scheme://$http_host/" proxy_cache off; add_header X-Docker-Caching-Proxy-Debug-Cache "no:default"; } - } }