Добрый день. Возможно, кому-то будет полезна данная информация. Мне в рамках некоторых рабочих задач понадобилось сохранить порядка 50 образов Docker и затем загрузить их в Docker на другом сервере.
За исходным кодом прошу под кат.
Код скрипта для сохранения образов (save-images.sh):
#!/bin/bash list="images.txt" images="images.tar.gz" usage() { echo "USAGE: $0 [--image-list images.txt] [--images images.tar.gz]" echo " [-l|--image-list path] text file with list of images; one image per line." echo " [-i|--images path] tar.gz generated by docker save." echo " [-h|--help] Usage message" } POSITIONAL=() while [[ $# -gt 0 ]]; do key="$1" case $key in -i | --images) images="$2" shift # past argument shift # past value ;; -l | --image-list) list="$2" shift # past argument shift # past value ;; -h | --help) help="true" shift ;; *) usage exit 1 ;; esac done if [[ $help ]]; then usage exit 0 fi pulled="" while IFS= read -r i; do [ -z "${i}" ] && continue if docker pull "${i}" >/dev/null 2>&1; then echo "Image pull success: ${i}" pulled="${pulled} ${i}" else if docker inspect "${i}" >/dev/null 2>&1; then pulled="${pulled} ${i}" else echo "Image pull failed: ${i}" fi fi done <"${list}" echo "Creating ${images} with $(echo ${pulled} | wc -w | tr -d '[:space:]') images" docker save $(echo ${pulled}) | gzip --stdout >${images}
Код для загрузки образов (load-images.sh):
#!/bin/bash images="images.tar.gz" list="images.txt" windows_image_list="" windows_versions="1809" usage() { echo "USAGE: $0 [--images images.tar.gz] --registry my.registry.com:5000" echo " [-l|--image-list path] text file with list of images; one image per line." echo " [-i|--images path] tar.gz generated by docker save." echo " [-r|--registry registry:port] target private registry:port." echo " [--windows-image-list path] text file with list of images used in Windows. Windows image mirroring is skipped when this is empty" echo " [--windows-versions version] Comma separated Windows versions. e.g., \"1809,2004,20H2\". (Default \"1809\")" echo " [-h|--help] Usage message" } push_manifest() { export DOCKER_CLI_EXPERIMENTAL=enabled manifest_list=() for i in "${arch_list[@]}"; do manifest_list+=("$1-${i}") done echo "Preparing manifest $1, list[${arch_list[@]}]" docker manifest create "$1" "${manifest_list[@]}" --amend docker manifest push "$1" --purge } while [[ $# -gt 0 ]]; do key="$1" case $key in -r | --registry) reg="$2" shift # past argument shift # past value ;; -l | --image-list) list="$2" shift # past argument shift # past value ;; -i | --images) images="$2" shift # past argument shift # past value ;; --windows-image-list) windows_image_list="$2" shift # past argument shift # past value ;; --windows-versions) windows_versions="$2" shift # past argument shift # past value ;; -h | --help) help="true" shift ;; *) usage exit 1 ;; esac done if [[ -z $reg ]]; then usage exit 1 fi if [[ $help ]]; then usage exit 0 fi docker load --input ${images} linux_images=() while IFS= read -r i; do [ -z "${i}" ] && continue linux_images+=("${i}") done <"${list}" arch_list=() if [[ -n "${windows_image_list}" ]]; then IFS=',' read -r -a versions <<<"$windows_versions" for version in "${versions[@]}"; do arch_list+=("windows-${version}") done windows_images=() while IFS= read -r i; do [ -z "${i}" ] && continue windows_images+=("${i}") done <"${windows_image_list}" # use manifest to publish images only used in Windows for i in "${windows_images[@]}"; do if [[ ! " ${linux_images[@]}" =~ " ${i}" ]]; then case $i in */*) image_name="${reg}/${i}" ;; *) image_name="${reg}/${i}" ;; esac push_manifest "${image_name}" fi done fi arch_list+=("linux-amd64") for i in "${linux_images[@]}"; do [ -z "${i}" ] && continue arch_suffix="" use_manifest=false if [[ (-n "${windows_image_list}") && " ${windows_images[@]}" =~ " ${i}" ]]; then # use manifest to publish images when it is used both in Linux and Windows use_manifest=true arch_suffix="-linux-amd64" fi case $i in */*) image_name="${reg}/${i}" ;; *) image_name="${reg}/${i}" ;; esac docker tag "${i}" "${image_name}${arch_suffix}" docker push "${image_name}${arch_suffix}" if $use_manifest; then push_manifest "${image_name}" fi done
Ну и формат списка образов это просто текстовый файл (images.txt):
quay.io/prometheus/prometheus:v2.36.1 quay.io/prometheus/node-exporter:v1.3.1 grafana/grafana:9.0.3
Инструкция по использованию:
Делаем файл save-images.sh исполняемым
chmod +x ./save-images.sh
И запускаем его
./save-images.sh --image-list ./images.txt
На выходе получаем архив images.tar.gz содержащий образы из списка. Для загрузки образов выполняем похожие операции
chmod +x load-images.sh
И загружаем образы из архива
./load-images.sh --image-list ./images.txt --registry <АДРЕС_ЛОКАЛЬНОГО_REGISTRY:ПОРТ>
Весь код доступен на GitHub: https://github.com/ZeroBot-Dot/docker-save-load-multiple-images
