This commit is contained in:
parent
68137b31c1
commit
996c79e4b4
@ -28,7 +28,8 @@ steps:
|
|||||||
privileged: true
|
privileged: true
|
||||||
environment:
|
environment:
|
||||||
REGISTRY: code.pztrn.name
|
REGISTRY: code.pztrn.name
|
||||||
REGISTRY_USER: drone
|
REGISTRY_PROJECT: /containers/mirrors
|
||||||
|
REGISTRY_USERNAME: drone
|
||||||
REGISTRY_PASSWORD:
|
REGISTRY_PASSWORD:
|
||||||
from_secret: drone_secret
|
from_secret: drone_secret
|
||||||
commands:
|
commands:
|
||||||
|
201
mirror.sh
201
mirror.sh
@ -1,80 +1,171 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# The Docker Image Mirror script.
|
# The Docker Image Mirror script.
|
||||||
WHAT_TO_MIRROR=()
|
# Designed to mirror amd64 and arm64 images somewhere you want.
|
||||||
DESTINATION_REGISTRY=${REGISTRY}
|
# Required environment variables:
|
||||||
DESTINATION_PROJECT=${DESTINATION_REGISTRY}/containers/mirror
|
#
|
||||||
USER=${REGISTRY_USER}
|
# * REGISTRY: to which registry images should be sent. Should not contain protocols,
|
||||||
PASSWORD=${REGISTRY_PASSWORD}
|
# should be the very same as you use 'docker login' with.
|
||||||
|
# * REGISTRY_USERNAME: user name to use for destination registry.
|
||||||
|
# * REGISTRY_PASSWORD: password to use for destination registry's user.
|
||||||
|
# * REGISTRY_PROJECT: path within registry (or it's part) where images will be push'd.
|
||||||
|
# Should start with '/'!
|
||||||
|
|
||||||
function mirror() {
|
# What images we will mirror. Collected by executing scripts in "images" directory, see
|
||||||
|
# "collect_images" function.
|
||||||
|
WHAT_TO_MIRROR=()
|
||||||
|
|
||||||
|
# New tag for currently processing image as it will be used with 'docker push'.
|
||||||
|
# Updates for every image. Contains only path, image name and base tag from source.
|
||||||
|
REMOTE_IMAGE=""
|
||||||
|
|
||||||
|
# Is image multiarch? E.g. is we're successfully fetched not only amd64 image,
|
||||||
|
# but also an arm64? Updates for every image.
|
||||||
|
MULTIARCH=0
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
local image=$1
|
local image=$1
|
||||||
local os_and_arch=$2
|
|
||||||
|
docker image rm "${image}" &> /dev/null
|
||||||
|
docker image rm "${REMOTE_IMAGE}" &> /dev/null
|
||||||
|
docker image rm "${REMOTE_IMAGE}"-amd64 &> /dev/null
|
||||||
|
docker image rm "${REMOTE_IMAGE}"-arm64 &> /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
function collect_images() {
|
||||||
|
# Load shell files and execute them to get list of mirrorred images.
|
||||||
|
MIRROR_CONFIGS=$(ls ./images/*.sh)
|
||||||
|
# shellcheck disable=SC2068
|
||||||
|
for file in ${MIRROR_CONFIGS[@]}; do
|
||||||
|
echo "Importing ${file}..."
|
||||||
|
# shellcheck disable=SC2086,SC2207,SC2206
|
||||||
|
WHAT_TO_MIRROR=( ${WHAT_TO_MIRROR[@]} $(bash ${file}) )
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Images to mirror: ${WHAT_TO_MIRROR[*]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_amd64_image() {
|
||||||
|
local image=$1
|
||||||
|
|
||||||
image_name=$(echo "${image}" | cut -d":" -f 1)
|
image_name=$(echo "${image}" | cut -d":" -f 1)
|
||||||
image_version=$(echo "${image}" | cut -d":" -f 2)
|
image_version=$(echo "${image}" | cut -d":" -f 2)
|
||||||
|
|
||||||
echo -n "Mirroring ${image} for '${os_and_arch}'... "
|
echo -ne "\t* Getting amd64 layers... "
|
||||||
|
|
||||||
|
# arm64 layers might be missing. So we just put "FAIL!" here and do nothing else.
|
||||||
|
if ! docker pull --platform=linux/amd64 "${image}" &> /dev/null; then
|
||||||
|
echo "FAIL!"
|
||||||
|
|
||||||
if ! docker pull --platform="${os_and_arch}" "${image}" &> /dev/null; then
|
return 1
|
||||||
echo "PULL FAILED"
|
fi
|
||||||
if [ "${os_and_arch/linux\/amd64//}" != "${os_and_arch}" ] ; then
|
|
||||||
exit 1
|
echo -n "Downloaded, "
|
||||||
fi
|
|
||||||
|
image_hash=$(docker images -a | grep "^${image_name}" | grep "${image_version}" | awk {' print $3 '})
|
||||||
|
|
||||||
|
if ! docker tag "${image_hash}" "${REMOTE_IMAGE}-amd64" &> /dev/null; then
|
||||||
|
echo "but tagging failed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "tagged."
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_arm64_image() {
|
||||||
|
local image=$1
|
||||||
|
|
||||||
|
image_name=$(echo "${image}" | cut -d":" -f 1)
|
||||||
|
image_version=$(echo "${image}" | cut -d":" -f 2)
|
||||||
|
|
||||||
|
echo -ne "\t* Getting arm64 layers... "
|
||||||
|
|
||||||
|
# arm64 layers might be missing. So we just put "FAIL!" here and do nothing else.
|
||||||
|
if ! docker pull --platform=linux/arm64 "${image}" &> /dev/null; then
|
||||||
|
echo "FAIL!"
|
||||||
|
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC1083
|
echo -n "Downloaded, "
|
||||||
|
|
||||||
image_hash=$(docker images -a | grep "^${image_name}" | grep "${image_version}" | awk {' print $3 '})
|
image_hash=$(docker images -a | grep "^${image_name}" | grep "${image_version}" | awk {' print $3 '})
|
||||||
echo -n "${image_hash} for '${os_and_arch}' received, retag as '${DESTINATION_PROJECT}/${image}'... "
|
|
||||||
|
|
||||||
|
if ! docker tag "${image_hash}" "${REMOTE_IMAGE}-arm64" &> /dev/null; then
|
||||||
if ! docker tag "${image_hash}" "${DESTINATION_PROJECT}/${image}" &> /dev/null; then
|
echo "but tagging failed!"
|
||||||
echo "TAGGING FAILED"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n "pushing... "
|
echo "tagged."
|
||||||
if ! docker push "${DESTINATION_PROJECT}/${image}" &> /dev/null; then
|
|
||||||
echo "FAILED"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "OK"
|
MULTIARCH=1
|
||||||
|
|
||||||
docker image rm "${image}" &> /dev/null
|
|
||||||
docker image rm "${DESTINATION_PROJECT}/${image}" &> /dev/null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Starting Docker daemon.
|
function login_to_registry() {
|
||||||
/usr/local/bin/dockerd --data-root=/var/lib/docker &
|
# Login to registry.
|
||||||
|
echo "Logging into '${REGISTRY}' as '${USER}'..."
|
||||||
|
docker login -u "${USER}" -p "${PASSWORD}" "${REGISTRY}"
|
||||||
|
}
|
||||||
|
|
||||||
# Wait for it.
|
function mirror() {
|
||||||
echo "Waiting for Docker daemon to start..."
|
local image=$1
|
||||||
while true; do
|
image_name=$(echo "${image}" | cut -d":" -f 1)
|
||||||
if docker ps &> /dev/null; then
|
image_version=$(echo "${image}" | cut -d":" -f 2)
|
||||||
break
|
|
||||||
|
echo "* Mirroring ${image}"
|
||||||
|
|
||||||
|
REMOTE_IMAGE="${REGISTRY}${REGISTRY_PROJECT}/${image}"
|
||||||
|
MULTIARCH=0
|
||||||
|
|
||||||
|
# We presumes that amd64 image should always be available.
|
||||||
|
if ! get_amd64_image "${image}"; then
|
||||||
|
echo "! Image mirroring failed! Cannot obtain amd64 image!"
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
get_arm64_image "${image}"
|
||||||
# Load shell files and execute them to get list of mirrorred images.
|
push_multiarch_image "${image}"
|
||||||
MIRROR_CONFIGS=$(ls ./images/*.sh)
|
cleanup "${image}"
|
||||||
# shellcheck disable=SC2068
|
}
|
||||||
for file in ${MIRROR_CONFIGS[@]}; do
|
|
||||||
echo "Importing ${file}..."
|
function push_multiarch_image() {
|
||||||
# shellcheck disable=SC2086,SC2207,SC2206
|
local image=$1
|
||||||
WHAT_TO_MIRROR=( ${WHAT_TO_MIRROR[@]} $(bash ${file}) )
|
|
||||||
done
|
if ! docker push "${REMOTE_IMAGE}"-amd64; then
|
||||||
|
echo -e "\t! amd64 image push failed!"
|
||||||
echo "Images to mirror: ${WHAT_TO_MIRROR[*]}"
|
fi
|
||||||
|
|
||||||
# Login to registry.
|
if ! docker push "${REMOTE_IMAGE}"-arm64; then
|
||||||
echo "Logging into '${DESTINATION_REGISTRY}' as '${USER}'..."
|
echo -e "\t! arm64 image push failed!"
|
||||||
docker login -u "${USER}" -p "${PASSWORD}" "${DESTINATION_REGISTRY}"
|
fi
|
||||||
|
|
||||||
# Mirror images.
|
if [ ${MULTIARCH} -eq 1 ]; then
|
||||||
for image in "${WHAT_TO_MIRROR[@]}"; do
|
echo -e "\t* Image is multi-arch, creating and pushing a manifest..."
|
||||||
mirror "${image}" linux/amd64
|
docker manifest create "${REMOTE_IMAGE}" \
|
||||||
#mirror "${image}" linux/arm64
|
--amend "${REMOTE_IMAGE}"-amd64 \
|
||||||
|
--amend "${REMOTE_IMAGE}"-arm64 \
|
||||||
|
&> /dev/null
|
||||||
|
|
||||||
|
docker manifest push "${REMOTE_IMAGE}" &> /dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function start_docker_daemon() {
|
||||||
|
# Starting Docker daemon.
|
||||||
|
/usr/local/bin/dockerd --data-root=/var/lib/docker &
|
||||||
|
|
||||||
|
# Wait for it.
|
||||||
|
echo "Waiting for Docker daemon to start..."
|
||||||
|
while true; do
|
||||||
|
if docker ps &> /dev/null; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
start_docker_daemon
|
||||||
|
login_to_registry
|
||||||
|
collect_images
|
||||||
|
|
||||||
|
for package in "${WHAT_TO_MIRROR[@]}"; do
|
||||||
|
mirror "${package}"
|
||||||
done
|
done
|
||||||
|
Loading…
Reference in New Issue
Block a user