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/
(默认保存目录) - 删除本地镜像和临时文件
使用步骤
- 保存脚本为
pull.sh
- 赋予执行权限:
chmod +x pull.sh
- 执行脚本:
./pull.sh nginx:latest
输出文件位于
/root/alist-doc/
,例如:nginx_latest_20250611.tar
示例命名规范
输入镜像名 | 输出文件名 |
---|---|
nginx:latest | nginx_latest_20250611.tar |
redis:7.2 | redis_7.2_20250611.tar |
busybox | busybox_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 自动更新问题的有效替代方案。