A tiny, memory‑friendly Docker/OCI image pusher for large images and constrained hosts.
Highlights:
- Streaming layer uploads with bounded memory
- Chunked uploads for large layers (auto‑adapts to registry hints)
- Clear progress reporting; resumable upload sessions
- Works with tar archives or directly from containerd
- Simple override:
docker.io/nginx:v1+--target gitea.corp.com/proj->gitea.corp.com/proj/nginx:v1
- Releases: download binaries from GitHub Releases
- Crates.io:
cargo install docker-image-pusher - From source:
git clone https://github.com/yorelog/docker-image-pusher cd docker-image-pusher && cargo build --release
-
Login (once per registry)
docker-image-pusher login registry.example.com --username user --password pass
Credentials are saved under
.docker-image-pusher/credentials.jsonand reused automatically. -
Save a local image to a tarball (optional)
docker-image-pusher save nginx:latest --out ./ # produces ./nginx_latest.tar -
Push the tar archive
docker-image-pusher push --tar ./nginx_latest.tar
- Use
--targetto set the exact destination. If omitted, we infer from tar metadata and (optionally)--registry. - If the destination was confirmed previously, we auto-continue after a short pause; otherwise we prompt once.
- Use
| Command | When to use | Key flags |
|---|---|---|
save [IMAGE ...] |
Export local images to tar/portable folder | --out, --root, --namespace, --digest |
push --tar <TAR> |
Upload a docker-save tar directly to a registry | -t/--target, --registry, --username/--password, --blob-chunk |
push --image <IMAGE> |
Push directly from containerd (no tar) | --root, --namespace, -t/--target, --username/--password, --blob-chunk |
login <registry> |
Persist credentials for future pushes | --username, --password |
- If the tar contains
docker.io/nginx:v1and you pass--target gitea.corp.com/project1, the final destination resolves togitea.corp.com/project1/nginx:v1(repo/tag taken from tar). - If you pass a full target like
--target gitea.corp.com/project1/nginx:custom, it is used as-is. --registryonly affects inference when--targetis not provided; it forces the registry host while keeping repo/tag from tar metadata.
docker-image-pusher login harbor.xxx.com --username USER --password PASS
docker-image-pusher push --tar ./app_1.0.0.tar \
--target harbor.xxx.com/org/app:1.0.0Notes:
- Use
--targetto specify the destination (registry/org/repo:tag) - Use
--registry harbor.xxx.comonly if a host override is needed --blob-chunksets chunk size (MiB) for large layers
docker-image-pusher push \
--root ~/.local/share/containerd \
--namespace default \
--image org/app:1.0.0 \
--target harbor.xxx.com/org/app:1.0.0Optional: export for offline delivery/audit, then push when needed:
docker-image-pusher save \
--root ~/.local/share/containerd \
--namespace default \
--out ./export \
org/app:1.0.0Tip: First push to a new target may ask for a one‑time confirmation based on history/metadata; subsequent pushes auto‑continue.
- Advanced architecture: see ARCHITECTURE.md
- Reusable OCI library: crates/oci-core/README.md
PRs and issues welcome. Happy pushing! 🐳