From 75a2a7e6cb3349844565aeeebd24431f27824ad7 Mon Sep 17 00:00:00 2001 From: Sunday Date: Mon, 3 Feb 2025 20:43:25 +0800 Subject: [PATCH] Add main shell script --- pull-docker-image.sh | 208 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 pull-docker-image.sh diff --git a/pull-docker-image.sh b/pull-docker-image.sh new file mode 100644 index 0000000..402e27a --- /dev/null +++ b/pull-docker-image.sh @@ -0,0 +1,208 @@ +#!/bin/bash +# pull-docker-image.sh +# 主要功能: +# - 根据用户参数拉取指定 Docker 镜像,生成 tar 包,并支持 gzip 或 zstd 压缩。 +# +# 具体参数与用法请见:pull-docker-image.sh -h + +set -euo pipefail + +# Default values. +IMAGE="" +DEST="." +NEWNAME="" +USE_GZIP=false +USE_ZSTD=false +FORCE=false +PROXY="" + +usage() { + cat <&2 + usage + exit 1 + fi + + # 如果未指定 -n,则使用 -t 的值 + if [[ -z "$NEWNAME" ]]; then + NEWNAME="$IMAGE" + fi + + # 压缩方法 -g 和 -z 不能同时指定 + if $USE_GZIP && $USE_ZSTD; then + echo "Error: '-g' and '-z' cannot be used together." >&2 + exit 1 + fi +} + +# 检查是否安装了 skopeo +check_skopeo() { + if ! command -v skopeo >/dev/null 2>&1; then + echo "Error: skopeo is not installed, or not in PATH." >&2 + exit 1 + fi +} + +# 设置网络代理 +setup_proxy() { + if [[ -n "$PROXY" ]]; then + export HTTP_PROXY="$PROXY" + export HTTPS_PROXY="$PROXY" + echo "Use proxy at $PROXY" + fi +} + +# 根据目标参数确定最终的目标文件路径 +determine_target_file() { + local target="" + if [[ -d "$DEST" ]]; then + local base_name + base_name=$(echo "$IMAGE" | tr ':' '_') + target="${DEST%/}/$base_name.tar" + else + target="$DEST" + fi + echo "$target" +} + +# 检查目标文件是否存在冲突 +check_conflict() { + local file="$1" + if [[ -f "$file" ]]; then + if ! $FORCE; then + echo "Error: destination file '$file' exists, use '-f' option to overwrite." >&2 + exit 1 + else + echo "Warning:destination file '$file' exists,override as '-f' specified." + fi + fi +} + +# 使用 skopeo 拉取 Docker 镜像 +pull_image() { + local target_file="$1" + echo "Start pulling $IMAGE to $target_file with name $NEWNAME in archive..." + if ! skopeo copy "docker://$IMAGE" "docker-archive:$target_file:$NEWNAME"; then + echo "Error: skopeo failed during pulling image" >&2 + exit 1 + fi + echo "Image is saved to $target_file successfully." +} + +# 根据压缩选项对镜像文件进行压缩 +compress_image() { + local target_file="$1" + local final_file="" + if $USE_GZIP || $USE_ZSTD; then + if $USE_GZIP; then + local compressed="${target_file}.gz" + check_conflict "$compressed" + echo "Compress $target_file with gzip..." + if ! gzip -f "$target_file"; then + echo "Error: failed to compress image with gzip." >&2 + exit 1 + fi + final_file="$compressed" + elif $USE_ZSTD; then + local compressed="${target_file}.zst" + check_conflict "$compressed" + echo "Compress $target_file with zstd..." + if ! zstd -q -o "$compressed" "$target_file"; then + echo "Error: failed to compress image with zstd." >&2 + exit 1 + fi + rm -f "$target_file" + final_file="$compressed" + fi + echo "Compressed image is saved to $final_file." + else + final_file="$target_file" + fi +} + +# 主函数 +main() { + parse_args "$@" + check_skopeo + setup_proxy + + local target_file + target_file=$(determine_target_file) + check_conflict "$target_file" + + # 同时检查压缩后的文件是否存在冲突(如果有压缩选项) + if $USE_GZIP; then + check_conflict "${target_file}.gz" + elif $USE_ZSTD; then + check_conflict "${target_file}.zst" + fi + + pull_image "$target_file" + compress_image "$target_file" + + echo "OK." +} + +# 主入口 +main "$@"