镜像同步常用脚本

#!/bin/bash
    desc='脚本说明:
1: 同步 arm、amd 镜像 (Docker Hub -> Harbor)
2: 导出镜像到本地 (从镜像地址 -> 本地 OCI 目录)
3: 导入镜像到 docker-daemon (本地 OCI 目录 -> Docker)
4: 导出镜像到本地 (指定私有仓库 -> 本地 OCI 目录)
5: 导入镜像到镜像仓库 (本地 OCI 目录 -> 目标仓库,保留原完整路径)
6: 同步amd64镜像到harbor (修复仅amd64的情况)
7: 导入镜像到 containerd (本地 OCI 目录 -> k8s/ctr)
8: 导入镜像到镜像仓库 (本地 OCI 目录 -> 目标仓库,**自动去除原域名**)

使用示例:
bash -x  image-tools.sh 1
bash -x  image-tools.sh 2 arm64
bash -x  image-tools.sh 3 arm64
bash -x  image-tools.sh 4 harbor.senses-ai.com arm64
bash -x  image-tools.sh 5 sealos.hub:5000 arm64
bash -x  image-tools.sh 6
bash -x  image-tools.sh 7 k8s.io arm64
bash -x  image-tools.sh 8 sealos.hub:5000 arm64
'

# 检查是否提供了位置参数
if [ $# -eq 0 ]; then
  echo "$desc"
  exit 1
fi

set -e

# 镜像列表文件
image_file="image.txt"

# 功能 1: 同步 arm、amd 镜像
sync_images() {
  while read -r image; do
    [[ -z "$image" || "$image" =~ ^# ]] && continue

    echo ">>> 处理镜像: $image"
    if [ ! -z $1 ]; then
      dest_project=base/${1}
    else
      dest_project=base
    fi

    src_project=''
    src_image="docker.1ms.run/${image}"

    # 目标镜像(多架构 manifest)
    dest_image="harbor.senses-ai.com/${dest_project}/${image}"

    echo "拉取 amd64"
    docker pull --platform linux/amd64 "$src_image"
    docker tag "$src_image" "${dest_image}-amd64"
    docker push "${dest_image}-amd64"

    echo "拉取 arm64"
    docker pull --platform linux/arm64 "$src_image"
    docker tag "$src_image" "${dest_image}-arm64"
    docker push "${dest_image}-arm64"

    # 删除中间镜像(可选)
    docker rmi "$src_image" || true

    # 创建 manifest
    docker manifest create --amend "$dest_image" \
      "${dest_image}-amd64" \
      "${dest_image}-arm64"

    # 注解(可选增强)
    docker manifest annotate "$dest_image" "${dest_image}-amd64" --os linux --arch amd64
    docker manifest annotate "$dest_image" "${dest_image}-arm64" --os linux --arch arm64

    # 推送 manifest
    docker manifest push "$dest_image"

    echo ">>> ✅ 完成镜像: $image"
    echo
  done < "$image_file"
}

# 功能 2: 导出镜像到本地
export_images() {
  while read -r image; do
    [[ -z "$image" || "$image" =~ ^# ]] && continue
    src_image="${image}"
    dest_image="${image}"
    arch=${1:-amd64}

    echo "导出镜像: $dest_image"
    skopeo copy  --insecure-policy  --multi-arch system --override-arch ${arch} --override-os linux "docker://${src_image}" "oci:data:${dest_image}"
    echo ">>> ✅ 镜像 $dest_image 导出完成"
  done < "$image_file"
}

# 功能 3: 导入镜像到 docker-daemon
import_images() {
  while read -r image; do
    [[ -z "$image" || "$image" =~ ^# ]] && continue

    src_image="${image}"
    dest_image="${image}"
    arch=${1:-amd64}

    echo "导入镜像: $dest_image"
    skopeo copy  --insecure-policy  --multi-arch system --override-arch ${arch} --override-os linux  "oci:data:${src_image}" "docker-daemon:${dest_image}"
    echo ">>> ✅ 镜像 $dest_image 导入完成"
  done < "$image_file"
}

# 功能 4: 导出镜像到本地 (指定源)
export_images_2() {
  while read -r image; do
    [[ -z "$image" || "$image" =~ ^# ]] && continue

    src_image="${image}"
    dest_image="${image}"
    src_repository=${1:-harbor.senses-ai.com}
    arch=${2:-amd64}

    echo "导出镜像: ${src_repository}/$dest_image"
    skopeo copy  --insecure-policy  --multi-arch system --override-arch ${arch} --override-os linux --dest-tls-verify=false --src-tls-verify=false "docker://${src_repository}/${dest_image}" "oci:data:${src_image}"
    echo ">>> ✅ 镜像 $dest_image 导出完成"
  done < "$image_file"
}

# 功能 5: 导入镜像到镜像仓库 (保留完��原路径)
import_images_2() {
  while read -r image; do
    [[ -z "$image" || "$image" =~ ^# ]] && continue

    src_image="${image}"
    dest_image="${image}"
    dest_repository=${1:-sealos.hub:5000}
    arch=${2:-amd64}

    echo "导入镜像: $dest_image"
    skopeo copy  --insecure-policy  --multi-arch system --override-arch ${arch} --override-os linux --dest-tls-verify=false --src-tls-verify=false "oci:data:${src_image}" "docker://${dest_repository}/${dest_image}"
    echo ">>> ✅ 镜像 $dest_image 导入完成"
  done < "$image_file"
}

# 功能 6: 同步amd64镜像到harbor
rsync_amd64() {
  while read -r image; do
    [[ -z "$image" || "$image" =~ ^# ]] && continue

    src_image="harbor.senses-ai.com/docker-hub/${image}"
    dest_image="${image}"
    dest_repository=${1:-harbor.senses-ai.com/base}
    arch=${2:-amd64}

    echo "导入镜像: $dest_image"
    skopeo copy  --insecure-policy  --multi-arch system --override-arch ${arch} --override-os linux --dest-tls-verify=false --src-tls-verify=false "docker://${src_image}" "docker://${dest_repository}/${dest_image}"
    echo ">>> ✅ 镜像 $dest_image 导入完成"
  done < "$image_file"
}

# 功能 7: 导入镜像到 containerd
import_to_containerd() {
  if ! command -v ctr &> /dev/null; then
    echo "错误: 未找到 ctr 命令。"
    exit 1
  fi
  namespace=${1:-k8s.io}
  arch=${2:-amd64}
  echo ">>> 目标命名空间: $namespace"

  while read -r image; do
    [[ -z "$image" || "$image" =~ ^# ]] && continue
    src_path="oci:data:${image}"
    tmp_tar="/tmp/import_ctr_${RANDOM}.tar"
    echo "正在转换并导入镜像: $image"
    if skopeo copy --insecure-policy --multi-arch system --override-arch ${arch} --override-os linux \
       "${src_path}" "docker-archive:${tmp_tar}:${image}"; then
       ctr -n "$namespace" images import "$tmp_tar"
       echo ">>> ✅ 镜像 $image 已导入到 containerd"
    fi
    rm -f "$tmp_tar"
  done < "$image_file"
}

# 功能 8: 从本地 OCI 导入到镜像仓库 (自动去域名)
import_oci_clean_push() {
  dest_repo=$1
  arch=${2:-amd64}

  [ -z "$dest_repo" ] && echo "❌ 错误: 请输入目标镜像仓库地址 (例如 sealos.hub:5000)" && exit 1

  while read -r image; do
    [[ -z "$image" || "$image" =~ ^# ]] && continue

    # 1. 确定本地 OCI 目录名
    # 因为功能 2 和 4 导出时,目录名就是 image.txt 里的完整字符串
    src_image="${image}"

    # 2. 构造目标镜像名 (截取域名)
    # 如果 image 是 "gcr.io/google_containers/pause:3.2",image_suffix 变为 "google_containers/pause:3.2"
    if [[ "$image" =~ ^[^/]+\.[^/]+/ ]]; then
         image_suffix="${image#*/}"
    else
         image_suffix="$image"
    fi

    # 目标完整地址
    dest_ref="docker://${dest_repo}/${image_suffix}"

    echo "-----------------------------------------------"
    echo "本地源: oci:data:${src_image}"
    echo "目标  : ${dest_ref}"

    # 3. 执行导入: 本地 OCI -> 目标 Registry
    skopeo copy --insecure-policy --multi-arch system --override-arch ${arch} --override-os linux \
      --src-tls-verify=false --dest-tls-verify=false \
      "oci:data:${src_image}" "$dest_ref"

    echo ">>> ✅ 导入成功: ${dest_repo}/${image_suffix}"
  done < "$image_file"
}

# 根据位置参数调用相应的功能
case "$1" in
  1)
    echo ">>> 执行功能 1: 同步 arm、amd 镜像"
    sync_images $2
    ;;
  2)
    echo ">>> 执行功能 2: 完整镜像地址导出到本地"
    export_images $2
    ;;
  3)
    echo ">>> 执行功能 3: 完整镜像地址导入到 docker-daemon"
    import_images $2
    ;;
  4)
    echo ">>> 执行功能 4: 导出镜像到本地 (指定源)"
    [ -z "$2" ] && echo "请输入镜像仓库地址" && exit 1
    export_images_2 $2 $3
    ;;
  5)
    echo ">>> 执行功能 5: 导入镜像到镜像仓库 (全名)"
    [ -z "$2" ] && echo "请输入镜像仓库地址" && exit 1
    import_images_2 $2 $3
    ;;
  6)
    echo ">>> 执行功能 6: 同步amd64镜像到 Harbor"
    rsync_amd64
    ;;
  7)
    echo ">>> 执行功能 7: 导入本地镜像到 containerd"
    import_to_containerd $2 $3
    ;;
  8)
    echo ">>> 执行功能 8: 导入本地镜像到仓库 (去域名)"
    # 参数2: 目标仓库, 参数3: 架构
    import_oci_clean_push $2 $3
    ;;

  *)
    echo "无效的参数! 请输入 1-8。"
    echo "$desc"
    exit 1
    ;;
esac
posted @ 2025-06-17 11:31  Tenderness、  阅读(31)  评论(0)    收藏  举报