Pull a container image from a remote registry through a SOCKS5 proxy and save it as a .tar file — no Docker daemon registry access required.
./docker-proxy-pull.sh [--proxy <host:port>] --image <image>--proxy defaults to localhost:20170 if omitted.
Examples:
./docker-proxy-pull.sh --image quay.io/calico/kube-controllers:v3.31.2
./docker-proxy-pull.sh --image quay.io/calico/kube-controllers:v3.31.2 --proxy 192.168.1.5:1080Produces quay.io_calico_kube-controllers_v3.31.2.tar in ./images/.
IMAGE=""
SOCKS_PROXY="localhost:20170"
# parsed from --image and --proxy flags
OUT="$(echo "$IMAGE" | sed 's#[/:]#_#g').tar"Takes --image (required) and --proxy (optional host:port). The output filename is derived from the image by replacing / and : with _ so it's a valid filename. quay.io/calico/node:v3.31.2 becomes quay.io_calico_node_v3.31.2.tar.
docker run --rm --network host \
...
quay.io/skopeo/stable:latest \
copy docker://"$IMAGE" docker-archive:/output/"$OUT":"$IMAGE"Skopeo is a tool that talks directly to container registry APIs without needing a Docker daemon. It's used here to pull the image and write it straight to a tar file.
--rm— removes the container after it exits--network host— the container shares the host's network stack, solocalhostinside the container resolves to the host machine (required when the proxy is running locally)copy docker://<image>— pull source: a remote registrydocker-archive:/output/<file>:<image>— save destination: a local tar file in Docker archive format, tagged with the original image reference so it loads correctly
-e HTTPS_PROXY=socks5h://"$SOCKS_PROXY"
-e https_proxy=socks5h://"$SOCKS_PROXY"
-e ALL_PROXY=socks5h://"$SOCKS_PROXY"
-e all_proxy=socks5h://"$SOCKS_PROXY"
-e NO_PROXY=""
-e no_proxy=""Skopeo is written in Go. Go's HTTP client reads these standard proxy environment variables to route outbound HTTPS traffic through the proxy.
All four proxy vars are set (uppercase and lowercase) because different Go versions and libraries check different casings.
The socks5h:// scheme (note the h) is critical — it tells Go to send the hostname to the proxy for DNS resolution rather than resolving it locally first. Without the h, Go resolves the hostname locally, gets blocked, and never reaches the proxy.
NO_PROXY and no_proxy are explicitly cleared to prevent any baked-in exclusion rules inside the skopeo image from bypassing the proxy.
-v "$PWD:/output"Mounts the current working directory into the container at /output. Skopeo writes the tar file there, making it accessible on the host after the container exits.
After copying the tar to your target machine (e.g. via scp), import it into containerd:
# Default namespace
ctr image import <file>.tar
# Kubernetes namespace (so kubelet can see it)
ctr -n k8s.io image import <file>.tarOr into Docker:
docker load -i <file>.tar- Docker installed and running on the host
- A SOCKS5 proxy reachable at the given address (default
localhost:20170) - Network access to the target registry via the proxy