一键拉取并打包 Docker 镜像(支持 Alist & Rclone)

hello world ! and say something say anything~

在国内使用 Docker 容器经常遇到镜像源更新滞后的问题。为了确保部署使用的是最新版本镜像,我们可以通过自定义脚本将镜像打包保存到本地或同步到 Rclone 存储,实现灵活、高效的镜像管理。

支持镜像离线分发(如通过 Alist 分享)
支持同步到任意 Rclone 支持的云盘,如 OneDrive、Google Drive、阿里云盘等
避免 Docker Compose 自动拉取新镜像,可使用:
docker compose up --no-pull


方案 A:打包 Docker 镜像并本地保存(适用于 Alist 分享)

一个简单的 Shell 脚本,支持一键拉取 Docker 镜像、打包为 .tar 文件并存储至指定目录,便于离线使用或归档。

功能说明

  • 输入 Docker 镜像名(如 nginx:latest
  • 自动拉取镜像
  • 保存为 .tar 文件,并命名为 镜像名_YYYYMMDD.tar
  • 移动文件至 /root/alist-doc/(默认保存目录)
  • 删除本地镜像和临时文件

使用步骤

  1. 保存脚本为 pull.sh
  2. 赋予执行权限:chmod +x pull.sh
  3. 执行脚本:./pull.sh nginx:latest

输出文件位于 /root/alist-doc/,例如:nginx_latest_20250611.tar

示例命名规范

输入镜像名输出文件名
nginx:latestnginx_latest_20250611.tar
redis:7.2redis_7.2_20250611.tar
busyboxbusybox_20250611.tar

注意事项

  • 默认保存路径为 /root/alist-doc/,需确保目录存在且有写权限
  • 镜像名中的 /: 会被替换为 _,以适配文件系统命名规范
  • 请确保网络可连接 registry-1.docker.io 以正常拉取镜像

脚本内容(pull.sh

#!/bin/bash

if [ -z "$1" ]; then
    echo "用法: $0 镜像名 (如 nginx:latest)"
    exit 1
fi

IMAGE_NAME="$1"
DATE_STR=$(date +%Y%m%d)
SANITIZED_NAME=$(echo "$IMAGE_NAME" | sed 's/[\/:]/_/g')
FILE_NAME="${SANITIZED_NAME}_${DATE_STR}.tar"
DEST_DIR="/root/alist-doc"
TMP_DIR="/tmp/docker_image_tmp"

mkdir -p "$TMP_DIR"

echo "拉取镜像: $IMAGE_NAME"
docker pull "$IMAGE_NAME" || { echo " 镜像拉取失败"; exit 1; }

echo "保存镜像为 TAR 文件"
docker save "$IMAGE_NAME" -o "$TMP_DIR/$FILE_NAME"

echo "移动 TAR 到目标目录: $DEST_DIR"
mkdir -p "$DEST_DIR"
mv "$TMP_DIR/$FILE_NAME" "$DEST_DIR/"

echo "删除 Docker 镜像: $IMAGE_NAME"
docker rmi "$IMAGE_NAME"

echo " 完成:已保存为 $DEST_DIR/$FILE_NAME"

方案 B:拉取镜像并上传到 Rclone 云存储

将镜像打包后自动上传至你配置好的 Rclone 云存储,适用于团队共享或在多台机器同步镜像。

脚本 A:拉取镜像 ➝ 打包 ➝ 上传 ➝ 清理

#!/bin/bash

read -p "请输入 Docker 镜像名字: " IMAGE_NAME

echo "正在下载 Docker 镜像: $IMAGE_NAME..."
docker pull $IMAGE_NAME

IMAGE_TAG=$(docker images --format "{{.Tag}}" $IMAGE_NAME | head -n 1)
PACKAGE_NAME="${IMAGE_NAME//\//_}_${IMAGE_TAG}.tar"

echo "正在打包镜像为: $PACKAGE_NAME..."
docker save -o $PACKAGE_NAME $IMAGE_NAME

RCLONE_REMOTE="your_rclone_remote_name"  # 替换为你的 Rclone 配置名
RCLONE_PATH="your_rclone_path"           # 替换为你的存储路径

echo "正在上传到 Rclone..."
rclone copy $PACKAGE_NAME $RCLONE_REMOTE:$RCLONE_PATH

if rclone ls $RCLONE_REMOTE:$RCLONE_PATH | grep -q $PACKAGE_NAME; then
    echo " 上传成功!正在清理本地镜像和文件..."
    docker rmi $IMAGE_NAME
    rm $PACKAGE_NAME
else
    echo "上传失败,请检查 Rclone 配置。"
fi

方案 C:从 Rclone 加载镜像回本地

支持从 Rclone 存储中选择 .tar 文件,自动下载并加载至本地 Docker,并清理上传文件。

脚本 B:下载 ➝ 加载 ➝ 修改标签 ➝ 清理

#!/bin/bash

export RCLONE_CONFIG="/home/ecs-user/.config/rclone/rclone.conf"
RCLONE_REMOTE="your_rclone_remote_name"
RCLONE_PATH="your_rclone_path"

echo "正在查找 Rclone 存储中的镜像文件..."
PACKAGE_NAME=$(rclone ls $RCLONE_REMOTE:$RCLONE_PATH | grep -oP '.*\.tar' | head -n 1)

if [ -z "$PACKAGE_NAME" ]; then
    echo "未找到任何 .tar 镜像文件"
    exit 1
fi

echo "找到文件: $PACKAGE_NAME"
IMAGE_NAME_WITH_TAG=$(basename $PACKAGE_NAME .tar)
IMAGE_NAME=$(echo $IMAGE_NAME_WITH_TAG | awk -F '_' '{print $1 "/" $2}')
IMAGE_TAG=$(echo $IMAGE_NAME_WITH_TAG | awk -F '_' '{print $NF}')

echo "解析镜像名: $IMAGE_NAME"
echo "解析标签: $IMAGE_TAG"

echo "下载中..."
rclone copy $RCLONE_REMOTE:$RCLONE_PATH/$PACKAGE_NAME .

echo "加载 Docker 镜像..."
docker load -i $PACKAGE_NAME

NEW_TAG="latest"
docker tag $IMAGE_NAME:$IMAGE_TAG $IMAGE_NAME:$NEW_TAG

if docker images | grep -q "$IMAGE_NAME"; then
    echo "镜像加载成功,开始清理..."
    rclone delete $RCLONE_REMOTE:$RCLONE_PATH/$PACKAGE_NAME
    rm $PACKAGE_NAME
else
    echo "镜像加载失败"
fi
 

使用提示

  • 文件命名应保持格式一致,例如:nginx_latest.tar
  • 脚本默认处理列表中第一个 .tar 文件,如需多文件批处理请扩展逻辑
  • 可手动修改 NEW_TAG 的值以指定加载后镜像的新标签

总结

通过上述三个脚本,你可以:

  • 在任意环境拉取镜像并打包
  • 通过 Alist 或 Rclone 分发镜像
  • 在其他主机快速加载镜像而无需联网

这是解决国内镜像拉取慢、Compose 自动更新问题的有效替代方案。

上一篇
下一篇