Skip to content

About

Download docker images from Docker Hub with proxy support written in pure Python. No docker daemon required.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Latest commit

 

History

17 Commits

Folders and files

Repository files navigation

Python Docker Downloader

Python Version License: MIT Dependencies GitHub Release GitHub Issues GitHub Stars Code Style: Ruff

A pure Python CLI tool for downloading Docker images without Docker itself. Single-file architecture with zero runtime dependencies, designed for air-gapped environments, corporate networks with proxy requirements, and seamless image transfers between systems.

Features

  • Zero Dependencies - Uses only the Python 3.11+ standard library
  • Registry v2/OCI Compatibility - Pulls from standard root-path Registry v2 endpoints
  • Corporate Proxy Support - Full HTTP/HTTPS proxy support with authentication
  • Multi-Architecture - Pull images for different architectures (amd64, arm64, etc.)
  • Progress Tracking - Real-time download progress with terminal-safe progress bars
  • Format Support - Handles Docker v2, OCI, and multi-architecture manifests
  • Integrity Verification - Verifies descriptor sizes and cryptographic digests before archiving

Installation

Option 1: Direct Download

# Download the script
curl -O https://raw.githubusercontent.com/ZacharyArthur/pythonDockerDownloader/main/docker_pull.py

Option 2: Git Clone

git clone https://github.com/ZacharyArthur/pythonDockerDownloader.git
cd pythonDockerDownloader

Requirements

  • Python 3.11 or later - No additional runtime dependencies required

Quick Start

# Pull an image
python3 docker_pull.py ubuntu:latest

# Pull with custom output name
python3 docker_pull.py nginx:alpine -o my-nginx.tar

# Load into Docker (if Docker is available)
docker load -i ubuntu_latest.tar

Usage

Basic Commands

# Pull latest image
python3 docker_pull.py ubuntu:latest

# Custom output name
python3 docker_pull.py nginx:alpine -o my-nginx.tar

# Different architecture
python3 docker_pull.py ubuntu:latest --arch arm64

# Select a specific ARM variant
python3 docker_pull.py alpine:latest --arch arm --variant v7

# Another public registry
python3 docker_pull.py icr.io/codeengine/helloworld:latest

# Private repository (username/password or a ready-made Bearer token)
printf '%s\n' "$REGISTRY_PASSWORD" | \
  python3 docker_pull.py registry.example.com/team/image:tag \
  --username "$REGISTRY_USER" --password-stdin
printf '%s\n' "$REGISTRY_TOKEN" | \
  python3 docker_pull.py registry.example.com/team/image:tag --token-stdin

# Digest-pinned pull (does not fabricate a RepoTag)
python3 docker_pull.py registry.example.com/team/image@sha256:DIGEST

# Trusted local development registry using plain HTTP
python3 docker_pull.py localhost:5000/team/image:tag --plain-http

Proxy Configuration

# Simple proxy setup
python3 docker_pull.py ubuntu:latest --proxy http://proxy.company.com:8080

# With authentication
python3 docker_pull.py ubuntu:latest \
  --proxy http://proxy.company.com:8080 \
  --proxy-auth username:password

# Environment variables
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1,.local
python3 docker_pull.py ubuntu:latest

# Corporate environment (disable SSL verification)
python3 docker_pull.py ubuntu:latest --proxy https://proxy.corp.com:8080 --insecure

Command Options

Option Description Default
-o, --output Output filename Derived from the image name and reference
--arch Target architecture amd64
--variant Target architecture variant, such as v6 or v7 for ARM None
--os Target OS linux
-t, --token Authentication token on the command line None
--token-stdin Read an authentication token from standard input False
--username Registry username None
--password Registry password or API key on the command line None
--password-stdin Read registry password or API key from standard input False
--proxy Proxy URL None
--proxy-auth Proxy credentials None
--http-proxy HTTP proxy URL, overriding the environment None
--https-proxy HTTPS proxy URL, overriding the environment None
--no-proxy Comma-separated hosts or host:port pairs that bypass proxies None
--insecure Disable SSL verification False
--plain-http Use HTTP for a trusted development registry False
--debug Enable debug output False
-v, --verbose Use INFO logging (the default) False
-q, --quiet Show only errors; suppress progress output False
--log-level Explicit DEBUG, INFO, WARNING, or ERROR logging None

Supported architectures: amd64, arm64, arm, 386, ppc64le, s390x, mips64le, riscv64. Use --variant when an image publishes multiple variants for the selected architecture. arm64/v8 also matches indexes that omit the default v8 variant.

If logging options are combined, precedence is --debug, --quiet, --log-level, then --verbose.

Registry Compatibility

The downloader uses the registry hostname in a fully-qualified image name and follows standard Registry v2 Bearer or Basic authentication challenges. No vendor-specific code is required. Registry hostnames are case-insensitive, but repository paths must be lowercase.

Registry Verification Image-name/authentication notes
Docker Hub Live archive check Short names such as alpine:latest, or any Docker Hub alias
GitHub Container Registry (GHCR) Live archive check ghcr.io/OWNER/IMAGE:TAG; private images use a username and PAT
GitLab Container Registry Live manifest/config check registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG; private images use GitLab-supported credentials or tokens
Quay.io Live archive check quay.io/ORG/IMAGE:TAG
Amazon Elastic Container Registry (ECR) ECR Public manifest/config; private protocol-reviewed public.ecr.aws/... or ACCOUNT.dkr.ecr.REGION.amazonaws.com/...
Google Artifact Registry Live public manifest/config check LOCATION-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG; credentialed pull not tested
Azure Container Registry (ACR) Protocol-reviewed NAME.azurecr.io/REPOSITORY/IMAGE:TAG; credentialed pull not tested
IBM Cloud Container Registry Live public manifest/config check REGION.icr.io/NAMESPACE/IMAGE:TAG; credentialed pull not tested
Oracle Cloud Infrastructure Registry (OCIR) Protocol-reviewed REGION.ocir.io/TENANCY/REPOSITORY:TAG; Oracle's separate public registry passed manifest/config checks
DigitalOcean Container Registry Protocol-reviewed registry.digitalocean.com/REGISTRY/IMAGE:TAG
Harbor Protocol-reviewed HOST/PROJECT/IMAGE:TAG; follows the deployment's Bearer or Basic challenge
CNCF Distribution (Docker Registry) Manual local testing HOST:PORT/IMAGE:TAG; add --plain-http only for a trusted HTTP development registry
Nexus Repository OSS Protocol-reviewed Docker connector hostname/port; no customer deployment tested
JFrog Artifactory Live public manifest/config check Docker repository hostname/subdomain method only; credentialed pull not tested
Red Hat Quay (self-hosted) Protocol-reviewed Quay hostname and repository path; no customer deployment tested

"Live archive check" means a complete image archive was downloaded and its layer diff-IDs were independently verified. "Live manifest/config check" means this implementation retrieved an image manifest and the selected platform's configuration blob. "Protocol-reviewed" means the documented Registry v2 flow and local tests match, but no vendor deployment was exercised. No credentialed private-registry pull has been verified end to end. Registries that expose the API under a path prefix instead of at /v2/ are not supported.

The checked Nextcloud images are nextcloud:latest on Docker Hub, which passed a live manifest/config check, and ghcr.io/nextcloud-releases/all-in-one:latest on GHCR, which passed a live archive check.

The complete registry.k8s.io/pause:3.9 flow was also verified through archive creation, including its fully-qualified RepoTags entry and uncompressed layer diff-ID.

Cloud Registry Credentials

Prefer short-lived credentials with --password-stdin or --token-stdin so secrets do not appear in command history or process listings. Multi-line passwords, such as JSON service-account keys, are accepted with --password-stdin; Bearer tokens must be a single line.

# Amazon ECR
aws ecr get-login-password --region us-east-1 | \
  python3 docker_pull.py ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/repository:tag \
  --username AWS --password-stdin

# Google Artifact Registry
gcloud auth print-access-token | \
  python3 docker_pull.py us-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG \
  --username oauth2accesstoken --password-stdin

# Azure Container Registry
az acr login --name NAME --expose-token --query accessToken -o tsv | \
  python3 docker_pull.py NAME.azurecr.io/repository:tag \
  --username 00000000-0000-0000-0000-000000000000 --password-stdin

# IBM Cloud Container Registry
printf '%s\n' "$IBM_CLOUD_API_KEY" | \
  python3 docker_pull.py icr.io/namespace/image:tag \
  --username iamapikey --password-stdin

--plain-http sends registry traffic, including credentials, without encryption. Use it only with a trusted local development registry. --insecure still uses HTTPS but disables certificate verification; use it only when you trust the endpoint and network. The two options are mutually exclusive.

How It Works

  1. Select Registry - Uses Docker Hub for short names or the registry in a fully-qualified image name
  2. Authenticate - Follows the registry's Bearer or Basic authentication challenge
  3. Get Manifest - Downloads up to 4 MiB of manifest/index JSON and selects the requested platform and optional --variant, normalizing registry-reported aarch64, x86_64, x86-64, i386, and arm64/v8 names; --arch accepts the canonical names listed above
  4. Download Layers - Streams layers to disk and verifies descriptor sizes/digests
  5. Create Archive - Verifies uncompressed layer diff-IDs and atomically replaces the output with a complete modern Docker/Podman-compatible tar

Supported Formats: Docker Registry v2, OCI images, multi-architecture manifests

Gzip and uncompressed layers are supported. Zstandard-compressed OCI layers, nested image indexes, schema v1 manifests, and foreign/nondistributable layers fail with clear errors. The foreign-layer limitation affects Windows images whose base layers are hosted outside the registry. OCI descriptors do not currently provide a standard uncompressed-layer size, so decompression has no arbitrary size cap; pull only from registries you trust.

Archives use manifest.json, as consumed by current Docker and Podman releases. Obsolete pre-manifest Docker archive metadata is not emitted.

Corporate Networks

For restrictive corporate environments:

# Typical corporate setup
export HTTPS_PROXY=https://proxy.corp.com:8080
export NO_PROXY=localhost,.corp.com
python3 docker_pull.py --insecure ubuntu:latest

Tips:

  • Use --insecure for self-signed proxy certificates
  • Add the selected registry to the proxy whitelist for better performance
  • Use --debug to troubleshoot connection issues

Troubleshooting

Proxy Issues:

  • Verify proxy URL and credentials with --debug
  • Try --insecure for certificate problems
  • Check NO_PROXY settings for the selected registry

Architecture Errors:

  • Available platforms are listed for multi-architecture images; --debug adds request-level detail
  • Some images don't support all architectures

Download Failures:

  • A timeout aborts the pull without replacing the output; check the network and retry. The extra per-chunk watchdog uses POSIX SIGALRM; Windows relies on the socket download timeout.
  • Check network connectivity and proxy configuration

Technical Details

Architecture

  • Single-file design - Complete functionality in docker_pull.py
  • Zero runtime dependencies - Uses only the Python 3.11+ standard library
  • Cross-platform compatibility - Works on Linux, macOS, and Windows; per-chunk SIGALRM enforcement is POSIX-only
  • CLI contract - docker_pull.py is the supported interface; internal classes are not a stable library API

Supported Image Formats

  • Docker Registry API v2
  • OCI (Open Container Initiative) images
  • Multi-architecture manifests
  • Private repository authentication

Code Quality

  • PEP 8 compliant - Formatted with Ruff
  • Static analysis - Ruff, Vulture, and Pyright checks
  • Comprehensive logging - Configurable log levels and quiet mode
  • Error handling - Graceful failure with helpful messages

Development

Running Tests

# Create the Python 3.11 environment and install locked development tools
uv sync --locked --python 3.11

# Activate it (choose one)
source .venv/bin/activate
# .\.venv\Scripts\Activate.ps1  # Windows PowerShell

# Run the test suite and syntax validation
uv run pytest -q
uv run python -m py_compile docker_pull.py test_docker_pull.py

Code Quality Checks

# Linting, formatting, dead-code, type, and test checks
uv run ruff check .
uv run ruff format --check .
uv run vulture docker_pull.py test_docker_pull.py
uv run pyright docker_pull.py test_docker_pull.py
uv run pytest -q

Requirements

  • Python 3.11 or later
  • No external dependencies - uses only standard library

License

MIT License - see LICENSE file for details.

Contributing

This project maintains a single-file, zero-dependency architecture for maximum portability. When contributing:

  • Maintain Python 3.11+ compatibility
  • Avoid external dependencies
  • Follow PEP 8 style guidelines
  • Include tests for new functionality
  • Preserve the single-file design

About

Download docker images from Docker Hub with proxy support written in pure Python. No docker daemon required.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages