Sign inSign up

waazaafr/docker-image-cloner

By waazaafr

β€’Updated 6 months ago

Clone images to personal registry.

Image
0

914

waazaafr/docker-image-cloner repository overview

⁠Docker Image Cloner

🐳 Keep a mirror of your favorite Docker images in your own registry, managed from a web interface.

Add the images you want to follow, and Docker Image Cloner regularly copies their most recent tags to your private registry. Images are copied directly from registry to registry with crane⁠: no Docker socket, no local pull, no disk space used on the host.


⁠Features

  • πŸ”„ Automatic synchronization every N hours, or on demand with one click
  • 🎯 Only the N most recent tags of each image are copied
  • πŸ“Œ Pin a specific tag (image:tag) to copy only that one
  • πŸ“¦ Sources: Docker Hub and any private registry
  • 🧩 Multi-arch images are copied with all their architectures
  • πŸ” Optional authentication on the source and target registries
  • 🌐 Web interface with live synchronization logs
  • πŸ–₯️ Multi-arch: linux/amd64 and linux/arm64

⁠Quick start

⁠Docker Compose
services:
  docker-image-cloner:
    image: waazaafr/docker-image-cloner:latest
    container_name: docker-image-cloner
    restart: unless-stopped
    ports:
      - "5000:5000"
    volumes:
      - ./data:/app/data
    environment:
      TARGET_REGISTRY: "registry.example.com"
      TARGET_REGISTRY_USERNAME: "myuser"
      TARGET_REGISTRY_PASSWORD: "mypassword"
      MAX_TAGS: 5
      SYNC_INTERVAL_HOURS: 6
⁠Docker run
docker run -d \
  --name docker-image-cloner \
  --restart unless-stopped \
  -p 5000:5000 \
  -v ./data:/app/data \
  -e TARGET_REGISTRY="registry.example.com" \
  -e TARGET_REGISTRY_USERNAME="myuser" \
  -e TARGET_REGISTRY_PASSWORD="mypassword" \
  -e MAX_TAGS=5 \
  -e SYNC_INTERVAL_HOURS=6 \
  waazaafr/docker-image-cloner:latest

Then open http://localhost:5000⁠, add the images to mirror, and click πŸ”„ Synchronize for a first sync.


⁠How it works

⁠Adding images
You addWhat is copied
linuxserver/jellyfinThe MAX_TAGS most recent tags from Docker Hub
nginxThe MAX_TAGS most recent tags of the official image
ghcr.io/owner/appThe MAX_TAGS most recent tags from that registry (see note below)
linuxserver/jellyfin:10.10.7Only the 10.10.7 tag

ℹ️ For registries other than Docker Hub, tags are listed anonymously. Registries that require a token to list tags (ghcr.io, quay.io, protected private registries…) fall back to latest only: add the tags you want explicitly (ghcr.io/owner/app:1.2).

⁠Naming in your registry

Images are stored as TARGET_REGISTRY/<image name>:<tag>, without the namespace:

  • linuxserver/jellyfin:latest β†’ registry.example.com/jellyfin:latest
  • ghcr.io/owner/app:1.2 β†’ registry.example.com/app:1.2

⚠️ Two images with the same name from different namespaces (e.g. linuxserver/jellyfin and jellyfin/jellyfin) end up in the same repository in your registry. Mirror only one of them.

⁠Synchronization
  • Automatic, every SYNC_INTERVAL_HOURS hours.
  • On demand, with the πŸ”„ Synchronize button.
  • Each run copies the selected tags of every image and shows the result live in the web interface.

⁠Configuration

⁠Environment variables
VariableDefaultRequiredDescription
TARGET_REGISTRYβ€”βœ…Your registry, where images are copied (e.g. registry.example.com)
TARGET_REGISTRY_USERNAMEβ€”Username for the target registry
TARGET_REGISTRY_PASSWORDβ€”Password or token for the target registry
SOURCE_REGISTRY_USERNAMEβ€”Username for private source registries (not used for Docker Hub)
SOURCE_REGISTRY_PASSWORDβ€”Password or token for private source registries
MAX_TAGS5Number of most recent tags copied per image
SYNC_INTERVAL_HOURS6Interval between automatic synchronizations, in hours
CRANE_INSECUREfalsetrue to allow registries over plain HTTP or with self-signed certificates
FLASK_PORT5000Port of the web interface
DATA_DIR/app/dataDirectory where the list of images is stored
⁠Authentication with an existing Docker login

Instead of the *_USERNAME / *_PASSWORD variables, you can reuse the credentials of the host (docker login) by mounting its Docker config file:

    volumes:
      - ./data:/app/data
      - ~/.docker/config.json:/root/.docker/config.json:ro

This is also the way to authenticate on Docker Hub, to avoid its anonymous pull rate limits.

⁠Volume
PathContent
/app/datarepositories.yaml: the list of mirrored images
⁠Port
PortService
5000Web interface

⁠Security

⚠️ The web interface has no authentication. Do not expose it on the internet: keep it on your LAN, or put it behind a reverse proxy with authentication.

  • Use HTTPS for your registry; enable CRANE_INSECURE only for a trusted local registry.
  • Registry credentials passed as environment variables are visible to anyone who can inspect the container.

⁠Troubleshooting

Logs of all synchronizations are available in the web interface and in the container logs:

docker logs -f docker-image-cloner
ErrorWhat to check
auth failed / UNAUTHORIZEDThe credentials of the registry, or the mounted config.json
TOOMANYREQUESTSDocker Hub rate limit: authenticate on Docker Hub (see above)
x509: certificate / http: server gave HTTP response to HTTPS clientYour registry uses HTTP or a self-signed certificate: set CRANE_INSECURE=true

MIT License β€” made with ❀️ by waazaa for the Docker community.

Tag summary

Content type

Image

Digest

sha256:d9a929adf…

Size

60.7 MB

Last updated

6 months ago

docker pull waazaafr/docker-image-cloner