#!/bin/bash #------------------------------------------------------------ # - Save docker images to disk or load images from disk # - Pull docker images from 'gcr.io|k8s.gcr.io|quay.io' # # @author: gjmzj # @usage: ./imgutils # @ref: https://github.com/easzlab/kubeasz/tree/master/tools/imgutils set -o nounset set -o errexit #set -o xtrace function usage() { echo -e "\033[33mUsage:\033[0m imgutils [options] [args]" cat < change image directory (default '/tmp/docker/images') -r limit to images who's repo have a pattern Example: $ ./imgutils -S -d /opt/docker/images -r gcr.io - to save all local images of repo 'gcr.io' into '/opt/docker/images/' $ ./imgutils -P k8s.gcr.io/addon-resizer:1.8.3 - to pull images from k8s.gcr.io EOF } function logger() { TIMESTAMP=$(date +'%Y-%m-%d %H:%M:%S') case "$1" in debug) echo -e "$TIMESTAMP \033[36mDEBUG\033[0m $2" ;; info) echo -e "$TIMESTAMP \033[32mINFO\033[0m $2" ;; warn) echo -e "$TIMESTAMP \033[33mWARN\033[0m $2" ;; error) echo -e "$TIMESTAMP \033[31mERROR\033[0m $2" ;; *) ;; esac } function save_to_disk() { if [[ "$REPO_PATTERN" == "" ]];then DOCKER_IMAGES=$(docker images|grep -v "^REPOSITORY"|awk '{print $1":"$2}') else DOCKER_IMAGES=$(docker images|grep "$REPO_PATTERN"|awk '{print $1":"$2}') fi # trim the last '/' in "$IMAGE_DIR" IMAGE_DIR=$(echo "$IMAGE_DIR"|sed 's/\/$//g') mkdir -p "$IMAGE_DIR" for image in ${DOCKER_IMAGES};do name=$(echo "$image"|sed 's/\//_/g'|sed 's/:/_/g') name="$IMAGE_DIR/$name.tar" logger info "packing $name..." docker save -o "$name" "$image" done } function load_from_disk() { [[ -d "$IMAGE_DIR" ]] || { logger error "Invald directory $IMAGE_DIR"; exit 1; } # trim the last '/' in "$IMAGE_DIR" IMAGE_DIR=$(echo "$IMAGE_DIR"|sed 's/\/$//g') if [[ "$REPO_PATTERN" == "" ]];then DOCKER_PACKS="$IMAGE_DIR/*.tar" else DOCKER_PACKS="$IMAGE_DIR/*$REPO_PATTERN*.tar" fi for pack in ${DOCKER_PACKS};do logger info "loading $pack..." docker load -i "$pack" done } function pull_any_image() { F=$(echo "$1"|awk -F/ '{print NF}') case "$F" in 1) HUB="docker.mirrors.ustc.edu.cn" GRP="library" IMG="$1" ;; 2) F1=$(echo "$1"|awk -F/ '{print $1}') F2=$(echo "$1"|awk -F/ '{print $2}') if [[ "$F1" == k8s.gcr.io ]];then HUB="gcr.mirrors.ustc.edu.cn" GRP="google-containers" IMG="$F2" else HUB="docker.mirrors.ustc.edu.cn" GRP="$F1" IMG="$F2" fi ;; 3) F1=$(echo "$1"|awk -F/ '{print $1}') F2=$(echo "$1"|awk -F/ '{print $2}') F3=$(echo "$1"|awk -F/ '{print $3}') if [[ "$F1" == quay.io ]];then HUB="quay.mirrors.ustc.edu.cn" elif [[ "$F1" == gcr.io ]];then HUB="gcr.mirrors.ustc.edu.cn" else logger warn "no mirror image for $1" HUB="$F1" fi GRP="$F2" IMG="$F3" ;; *) logger error "Invald image $1" exit 1 ;; esac logger info "Using mirror $HUB/$GRP/$IMG" docker pull "$HUB/$GRP/$IMG" && \ docker tag "$HUB/$GRP/$IMG" "$1" && \ docker rmi "$HUB/$GRP/$IMG" } function main() { # check if use bash shell readlink /proc/$$/exe|grep -q "dash" && { logger error "you should use bash shell, not sh"; exit 1; } # check if use with root [[ "$EUID" -ne 0 ]] && { logger error "you should run this script as root"; exit 1; } # check num of args [[ "$#" -eq 0 ]] && { usage >&2; exit 1; } export IMAGE_DIR="/tmp/docker/images" export REPO_PATTERN="" export ACTION="" while getopts "LP:Sd:r:" OPTION; do case "$OPTION" in L) ACTION="load_from_disk" ;; P) ACTION="pull_any_image $OPTARG" ;; S) ACTION="save_to_disk" ;; d) export IMAGE_DIR="$OPTARG" ;; r) export REPO_PATTERN="$OPTARG" ;; ?) usage exit 1 ;; esac done [[ "$ACTION" == "" ]] && { logger error "illegal option"; usage; exit 1; } # excute cmd "$ACTION" logger debug "Action begin: $ACTION" ${ACTION} || { logger error "Action failed: $ACTION"; return 1; } logger debug "Action successed: $ACTION" } main "$@"