批量下载导出指定版本Docker镜像

这里以OpenVPN Access Server为例,通过网页https://hub.docker.com/r/openvpn/openvpn-as获取版本列表,填入到以下代码VERSIONS这里,一行一个版本。将脚本保存为到 /opt/openvpn.sh


修复换行符(解决 $’\r’ 报错,如果报错的话,执行下):
dos2unix openvpn.sh


授权sh脚本运行
chmod +x openvpn.sh
bash ./openvpn.sh


删除所有openvpn-as镜像
docker images | grep “openvpn/openvpn-as” | awk ‘{print $3}’ | xargs -r docker rmi

脚本中的变量,IMAGE_REPO 是镜像名称,EXPORT_DIR是导出备份包的位置,VERSIONS下面一行一个版本。想下载其它镜像可以修改这几个变量及版本号。

#!/bin/bash

# ==========================================
# 配置区
# ==========================================

# 1. 镜像仓库地址 (请根据实际情况修改)
# 如果是 Docker Hub 公开镜像: "openvpn/openvpn-as"
# 如果是私有仓库: "registry.yourcompany.com/openvpn/as"
IMAGE_REPO="openvpn/openvpn-as"

# 2. 导出目标目录
EXPORT_DIR="/opt/openvpn"

# 3. 版本列表
VERSIONS=(
    "3.2.3-8444f22d-Ubuntu26"
    "3.2.2-413ca39f-Ubuntu24"
    "3.1.0-e22fe316-Ubuntu24"
    "3.0.2-87c70987-Ubuntu24"
    "3.0.1-84b60e70-Ubuntu24"
    "2.14.3-5936bcd7-Ubuntu24"
    "2.14.2-40b190d8-Ubuntu24"
    "2.14.1-ff013d4d-Ubuntu22"
    "2.14.0-b90cb316-Ubuntu22"
    "2.13.1-d8cdeb9c-Ubuntu22"
    "2.13.0-c7623b5a-Ubuntu22"
    "2.12.3-76774795-Ubuntu22"
    "2.12.1-bc070def-Ubuntu22"
)

# ==========================================
# 前置检查与目录创建
# ==========================================

# 检查并创建目标目录 (如果不存在则自动创建)
if [ ! -d "$EXPORT_DIR" ]; then
    echo "目录 $EXPORT_DIR 不存在,正在创建..."
    # 如果是普通用户运行,可能需要 sudo; 如果是 root 运行则直接创建
    if [ -w "/opt" ]; then
        mkdir -p "$EXPORT_DIR"
    else
        sudo mkdir -p "$EXPORT_DIR"
    fi
    echo "目录创建成功。"
fi

# 检查是否拥有 Docker 命令
if ! command -v docker &> /dev/null; then
    echo "错误: 未找到 docker 命令,请确保已安装并启动 Docker。"
    exit 1
fi

# ==========================================
# 主循环
# ==========================================

echo "开始处理镜像..."
echo "仓库: $IMAGE_REPO"
echo "导出目录: $EXPORT_DIR"
echo "---------------------------------------------"

SUCCESS_COUNT=0
FAIL_COUNT=0
SKIP_COUNT=0

for TAG in "${VERSIONS[@]}"; do
    FULL_IMAGE_NAME="$IMAGE_REPO:$TAG"
    OUTPUT_FILE="$EXPORT_DIR/$TAG.tar"
    
    echo ""
    echo "[开始] 处理 $FULL_IMAGE_NAME"

    # 1. 检查本地文件是否已存在 (跳过已处理的)
    if [ -f "$OUTPUT_FILE" ]; then
        echo "  [跳过] 文件 $OUTPUT_FILE 已存在。如需重新下载,请先删除该文件。"
        SKIP_COUNT=$((SKIP_COUNT + 1))
        continue
    fi

    # 2. 拉取镜像
    echo "  -> 正在拉取镜像..."
    if ! docker pull "$FULL_IMAGE_NAME"; then
        echo "  [错误] 无法拉取镜像 $FULL_IMAGE_NAME,跳过。"
        FAIL_COUNT=$((FAIL_COUNT + 1))
        continue
    fi
    
    # 3. 导出镜像为 tar 包
    echo "  -> 正在导出到 $OUTPUT_FILE ..."
    if docker save -o "$OUTPUT_FILE" "$FULL_IMAGE_NAME"; then
        echo "  [成功] 导出完成: $OUTPUT_FILE"
        SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
        
        # 可选:清理本地镜像以节省空间
        # docker rmi "$FULL_IMAGE_NAME" > /dev/null 2>&1
        # echo "  [清理] 已删除本地镜像"
    else
        echo "  [错误] 导出失败。"
        FAIL_COUNT=$((FAIL_COUNT + 1))
    fi
    
done

echo ""
echo "---------------------------------------------"
echo "处理完成!"
echo "成功: $SUCCESS_COUNT"
echo "失败: $FAIL_COUNT"
echo "跳过(已存在): $SKIP_COUNT"
echo "文件保存在: $EXPORT_DIR"