Complete script rework.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Stanislav Nikitin 2022-06-28 20:15:13 +05:00
parent 68137b31c1
commit 996c79e4b4
Signed by: pztrn
GPG Key ID: 1E944A0F0568B550
2 changed files with 148 additions and 56 deletions

View File

@ -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
View File

@ -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