如何将Docker Registry存储中的Docker镜像迁移到Harbor
作者:学亮编程手记
这篇文章主要介绍了如何将Docker Registry存储中的Docker镜像迁移到Harbor问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
Docker Registry存储的Docker镜像迁移到Harbor
#!/bin/bash
REGISTRY_PATH="/var/lib/registry"
REGISTRY_DOMAIN="${1}"
REGISTRY_USER="${2}"
REGISTRY_PWD="${3}"
# 切换到 registry 存储主目录下
cd ${REGISTRY_PATH}
gen_skopeo_dir() {
# 定义 registry 存储的 blob 目录 和 repositories 目录,方便后面使用
BLOB_DIR="docker/registry/v2/blobs/sha256"
REPO_DIR="docker/registry/v2/repositories"
# 定义生成 skopeo 目录
SKOPEO_DIR="docker/skopeo"
# 通过 find 出 current 文件夹可以得到所有带 tag 的镜像,因为一个 tag 对应一个 current 目录
for image in $(find ${REPO_DIR} -type d -name "current"); do
# 根据镜像的 tag 提取镜像的名字
name=$(echo ${image} | awk -F '/' '{print $5"/"$6":"$9}')
link=$(cat ${image}/link | sed 's/sha256://')
mfs="${BLOB_DIR}/${link:0:2}/${link}/data"
# 创建镜像的硬链接需要的目录
mkdir -p "${SKOPEO_DIR}/${name}"
# 硬链接镜像的 manifests 文件到目录的 manifest 文件
ln -f ${mfs} ${SKOPEO_DIR}/${name}/manifest.json
# 使用正则匹配出所有的 sha256 值,然后排序去重
layers=$(grep -Eo "\b[a-f0-9]{64}\b" ${mfs} | sort -n | uniq)
for layer in ${layers}; do
# 硬链接 registry 存储目录里的镜像 layer 和 images config 到镜像的 dir 目录
ln -f ${BLOB_DIR}/${layer:0:2}/${layer}/data ${SKOPEO_DIR}/${name}/${layer}
done
done
}
sync_image() {
# 使用 skopeo sync 将 dir 格式的镜像同步到 harbor
for project in $(ls ${SKOPEO_DIR}); do
skopeo sync --insecure-policy --src-tls-verify=false --dest-tls-verify=false \
--dest-creds ${REGISTRY_USER}:${REGISTRY_PWD} \
--src dir --dest docker ${SKOPEO_DIR}/${project} ${REGISTRY_DOMAIN}
done
}
gen_skopeo_dir
sync_image该脚本用于将 Docker Registry 存储中的镜像迁移到 Harbor 或其他兼容的镜像仓库,核心逻辑分为两步:
- 生成符合 Skopeo 要求的目录结构(
gen_skopeo_dir函数) - 使用 Skopeo 同步镜像到目标仓库(
sync_image函数)
逐段代码解析
1. 初始化参数与路径
REGISTRY_PATH="/var/lib/registry" # Docker Registry 存储根目录
REGISTRY_DOMAIN="${1}" # 目标 Harbor 域名(如 harbor.example.com)
REGISTRY_USER="${2}" # Harbor 用户名
REGISTRY_PWD="${3}" # Harbor 密码- 作用:接收用户输入的 Harbor 地址和认证信息,并指定 Registry 存储路径。
2. 生成 Skopeo 目录结构(gen_skopeo_dir)
BLOB_DIR="docker/registry/v2/blobs/sha256" # 镜像 Blob 存储路径
REPO_DIR="docker/registry/v2/repositories" # 镜像元数据存储路径
SKOPEO_DIR="docker/skopeo" # Skopeo 临时目录
for image in $(find ${REPO_DIR} -type d -name "current"); do
name=$(echo ${image} | awk -F '/' '{print $5"/"$6":"$9}') # 提取镜像名(格式:项目/镜像:标签)
link=$(cat ${image}/link | sed 's/sha256://') # 获取 Manifest 的 SHA256 值
mfs="${BLOB_DIR}/${link:0:2}/${link}/data" # 定位 Manifest 文件路径
mkdir -p "${SKOPEO_DIR}/${name}" # 创建镜像目录
ln -f ${mfs} ${SKOPEO_DIR}/${name}/manifest.json # 硬链接 Manifest 文件
layers=$(grep -Eo "\b[a-f0-9]{64}\b" ${mfs} | sort -n | uniq) # 提取所有 Layer SHA256
for layer in ${layers}; do
ln -f ${BLOB_DIR}/${layer:0:2}/${layer}/data ${SKOPEO_DIR}/${name}/${layer} # 硬链接 Layer 文件
done
done核心功能:
- 遍历 Registry 存储目录中的每个镜像 Tag(通过
current目录标识)。 - 通过硬链接(
ln -f)复用 Registry 存储中的 Blob 文件,避免磁盘复制开销。 - 生成符合 Skopeo
dir格式的目录结构,包含manifest.json和 Layer 文件。
3. 同步镜像到 Harbor(sync_image)
for project in $(ls ${SKOPEO_DIR}); do
skopeo sync --insecure-policy --src-tls-verify=false --dest-tls-verify=false \
--dest-creds ${REGISTRY_USER}:${REGISTRY_PWD} \
--src dir --dest docker ${SKOPEO_DIR}/${project} ${REGISTRY_DOMAIN}
done核心功能:
- 使用
skopeo sync命令将生成的dir格式镜像同步到 Harbor。 --dest-creds指定 Harbor 的认证信息,--src-tls-verify=false忽略源/目标的 TLS 验证(适用于非 HTTPS 或自签名证书环境)。- 按项目(Project)逐一批量同步镜像。
关键技术原理
硬链接优化:
- 直接通过文件系统硬链接复用 Registry 存储中的 Blob 文件,减少磁盘 I/O 和时间消耗。
Skopeo 目录格式:
dir格式是 Skopeo 支持的本地镜像存储格式,包含manifest.json和未压缩的 Layer 文件。
Harbor 兼容性:
- 适用于 Harbor 2.x 版本(需通过 API 推送镜像,直接复制存储目录已失效)。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
