How to locally backup the images of a local Docker-registry?
Asked Answered
T

2

3
  • How to create a local-registry container that mounts a volume from the host machine and persist locally all the images that get pulled?

Local Docker registry with persisted images

It should be possible to have an ephemeral registry container (and its docker volume), allowing to not download images more than once, even after the registry (or the whole Docker VM) is being throw away and recreated.

This would allow to pull just once the images, having them available when internet connectivity isn't good (or available at all); would allow also to mount a docker volume with pre-downloaded images.
It would be more convenient than having to manually docker push/docker pull onto the local registry, or to docker save/docker load each image that need to be available there.

Notes:

  • destination of the mount should probably be /var/lib/registry/docker/registry.
  • it is possible to configure a local Docker registry as a pull-through cache.
  • my specific setup runs docker via minikube, on macOS; but the answer doesn't have to be specific to it.
Titanomachy answered 9/4, 2021 at 21:28 Comment(0)
T
0

I managed it, here are the step-by-step instructions. Hopefully will make life easier to somebody else!

Configuration

Define first your environment variables with the desired values. See env-vars in the code below (PROXIED_REGISTRY, REGISTRY_USERNAME, REGISTRY_PASSWORD, PATH_WHERE_TO_PERSIST_IMAGES, etc.)

On the host machine

Minikube

If using minikube, first bind to docker on its VM's

eval $(minikube docker-env)

or run the commands directly from inside the VM, via minikube ssh.

Create local registry

(note: some envs might be unnecessary; check Docker docs to see what you need)

The -v option mounts onto the local registry the path where you want to persist the registry data (repositories folders and image layers).
When you use Minikube, this latter will automatically mount the home folder from the host (/Users/, on macOS) onto the virtual machine where Docker is run.

docker run -d -p 5000:5000 \
    -e STANDALONE=false \
    -e "REGISTRY_LOG_LEVEL=debug" \
    -e "REGISTRY_REDIRECT_DISABLE=true" \
    -e MIRROR_SOURCE="https://${PROXIED_REGISTRY}" \
    -e REGISTRY_PROXY_REMOTEURL="https://${PROXIED_REGISTRY}" \
    -e REGISTRY_PROXY_USERNAME="${REGISTRY_USER}" \
    -e REGISTRY_PROXY_PASSWORD="${REGISTRY_PASSWORD}" \
    -v /Users/${MACOS_USERNAME}/${PATH_WHERE_TO_PERSIST_IMAGES}/docker/registry:/var/lib/registry \
    --restart=always \
    --name local-registry \
    registry:2

Login to your local registry

echo -n "${REGISTRY_PASSWORD}" | docker login -u "${REGISTRY_USER}" --password-stdin "localhost:5000"

(optional) Verify that the persist directories are present

docker exec registry ls -la /var/lib/registry/docker/registry
ll /Users/${MACOS_USERNAME}/${PATH_WHERE_TO_PERSIST_IMAGES}/docker/registry/docker/registry

Try to pull one image from your private registry

(to see it proxied through the repository localhost:5000)

docker pull localhost:5000/${REPOSITORY}/${IMAGE}:${IMAGE_TAG}

(optional) Verify the image data has been synced on local host, where desired

docker exec registry ls -la /var/lib/registry/docker/registry
ll /Users/${MACOS_USERNAME}/${PATH_WHERE_TO_PERSIST_IMAGES}/docker/registry/docker/registry

If using Kubernetes

change the deployment spec container image to:

localhost:5000/${REPOSITORY}/${IMAGE}:${IMAGE_TAG}

Et voila!
You now can keep the images downloaded from your repository stored onto your host machine!
If internet is available, the local registry will ensure to have the most recent version of your pulled images, requesting it to the proxied registry (private, or the the Docker hub).

And you will have a last resort backup to run your container also when your internet connection is too slow for re-downloading everything you need, or is unavailable altogether!
(really useful with Minikube, when you need to destroy your docker virtual machine)


References:

Titanomachy answered 10/4, 2021 at 4:20 Comment(0)
D
0

The following code works great to backup locally registry:2 images.
It works also to move or push those images to a secondary docker registry.

#!/usr/bin/env bash

user=john
pass=a1b2c3d4e5f6
origin=docker.host.io
dest=docker.otherhost.io

# Grab catalog
repoList=$(curl -s -X GET -k "https://$user:$pass@$origin/v2/_catalog" | jq -r '.repositories[]')

# Craft repo names for the last 3 tags for each repo
# Remove `[0:3]` to backup all tags
repoTagList=$(for r in $repoList; do curl -s -X GET -k "https://$user:$pass@$origin/v2/$r/tags/list" | jq -r '"'$r':"+ .tags[0:3][]' | sort; done)

for repo in repoTagList; do
    echo "Backing up $repo";
    docker pull $origin/$repo;
    # comment out these lines to avoid upload
    docker tag $origin/$repo $dest/$repo;
    docker push $dest/$repo;
    # comment out this line to keep images locally
    docker rmi $origin/$repo;
done

Demibastion answered 14/4 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.