Skip to content

使用 regctl 将远程镜像复制到目标可用区 Registry

regctl 可以直接在两个远程 Registry 之间复制镜像,不要求本地设备安装或启动 Docker Engine,也不会把镜像导入本地 Docker 镜像存储。本教程适用于本地设备能够访问源 Registry 和目标可用区 Registry 公网地址的场景。

如果镜像已经存在于本地 Docker Engine,直接使用 docker push;在同一平台、同一租户的可用区之间迁移镜像时,优先使用镜像中心的 同步 功能。完整的平台导入和迁移方式参见导入或跨可用区迁移镜像。已有经过验证的 crane 脚本,或依赖 --all-tags--no-clobber 等 crane 选项时,可以继续使用使用 crane 检查、管理和传输容器镜像

注意

第三方可选工具

regctl 是需要自行安装的第三方工具,不属于平台服务等级协议的保障范围。本文命令按 v0.11.5 核对;用于生产环境或 CI 时,请固定并验证所用版本。

安装并确认 regctl 版本

macOS 可以通过 Homebrew 安装:

language-shell
brew install regclient
regctl version

Linux 和 Windows 用户可以从 regclient Releases下载与操作系统及架构匹配的二进制文件,并按官方安装说明验证下载内容。安装后运行:

language-shell
regctl version

确认 regctl 已加入 PATH,并且输出版本符合预期。

登录目标可用区 Registry

平台的 Registry 按可用区相互独立。先在镜像中心选择镜像实际要使用的目标可用区,复制页面显示的 Registry 公网访问地址、用户名和密码。地址选择规则参见镜像仓库地址与可用区

从本地设备执行复制时,必须使用目标可用区 Registry 公网访问地址cr.infini-ai.com 是平台实例访问其所在可用区 Registry 的内部地址,不能用于本地导入。

language-shell
export DST_REGISTRY="<目标可用区 Registry 公网访问地址>"
export DST_USERNAME="<镜像中心提供的用户名>"

read -rsp 'Registry password: ' DST_PASSWORD
printf '%s' "$DST_PASSWORD" |
  regctl registry login "$DST_REGISTRY" \
    --user "$DST_USERNAME" \
    --pass-stdin
unset DST_PASSWORD

--pass-stdin 可以避免密码出现在 Shell 历史和进程参数中。regctl 会把凭证写入当前用户的配置;不要打印或提交该配置文件。

登录私有 Docker Hub 镜像

Docker Hub 公有镜像通常可以匿名读取。源镜像为私有镜像,或需要避免匿名读取限额时,再使用 Docker Hub 用户名和访问令牌登录:

language-shell
export DOCKERHUB_USERNAME="<Docker Hub 用户名>"
read -rsp 'Docker Hub access token: ' DOCKERHUB_TOKEN
printf '%s' "$DOCKERHUB_TOKEN" |
  regctl registry login docker.io \
    --user "$DOCKERHUB_USERNAME" \
    --pass-stdin
unset DOCKERHUB_TOKEN

复制目标架构的镜像

定义源镜像、目标镜像和目标平台。以下示例把 Docker Hub 中的 Ubuntu 22.04 Linux AMD64 镜像复制到目标可用区 Registry:

language-shell
export PLATFORM="linux/amd64"
export SRC_IMAGE="docker.io/library/ubuntu:22.04"
export DST_IMAGE="$DST_REGISTRY/<租户 ID>/ubuntu:22.04"

SRC_DIGEST="$(
  regctl image digest \
    --platform "$PLATFORM" \
    "$SRC_IMAGE"
)"

regctl image copy \
  --platform "$PLATFORM" \
  "$SRC_IMAGE" \
  "$DST_IMAGE"

读取源摘要同时会确认源镜像包含目标平台。如果命令找不到 linux/amd64,请改选合适的上游镜像,或返回构建流程生成目标架构。

--platform linux/amd64 只复制该平台对应的镜像配置和镜像层。需要保留完整多架构镜像时,不要添加 --platform,并在验证时比较同一层级的摘要。

regctl 只会传输目标端缺失且无法挂载复用的镜像层。镜像数据仍会经过运行 regctl 的设备,因此速度受源端下载、目标端上传和本地网络共同影响。

验证目标摘要并试运行镜像

复制完成后,读取目标镜像的同平台摘要,并与复制前记录的源摘要比较:

language-shell
DST_DIGEST="$(
  regctl image digest \
    --platform "$PLATFORM" \
    "$DST_IMAGE"
)"

printf 'source:      %s\ndestination: %s\n' \
  "$SRC_DIGEST" \
  "$DST_DIGEST"
test "$SRC_DIGEST" = "$DST_DIGEST"

摘要一致后,返回镜像中心确认镜像出现在预期可用区,并创建测试实例,验证平台能够拉取、启动和运行目标镜像。用于开发机前,还要确认镜像包含开发机基础组件

为单个大镜像层启用分块上传

普通镜像和稳定链路先使用默认的 regctl image copy。已知镜像包含数百 MiB 至数 GiB 的单个层、上传链路容易超时,或同一个大层已经反复上传失败时,再为目标 Registry 主机配置分块上传。

需要确认单层大小时,查看镜像清单中 Layers 下每个 descriptor 的 Size

language-shell
regctl manifest get \
  --platform "$PLATFORM" \
  "$SRC_IMAGE"

regctl 默认会尝试完整上传,并在失败且输入可以重新读取时回退到分块上传。与 crane copy 相比,regctl 还提供目标主机级别的完整上传阈值和分块大小设置,可以让已知的大层直接使用分块协议:

language-shell
regctl registry set "$DST_REGISTRY" \
  --blob-max 536870912 \
  --blob-chunk 33554432

这组配置表示:

  • 大于 512 MiB 的 blob 直接使用分块协议;
  • 每次分块数据请求最多传输 32 MiB。

在没有明确网关限制或既往失败数据时,512 MiB 是兼顾兼容性和大层上传稳定性的建议起点:普通小层仍使用完整上传,较大的 AI、CUDA 或自制镜像层则直接分块。32 MiB 分块可以降低单次失败的重传量,但过小会增加协议开销,过大则可能再次触发超时或请求体限制。这组值不是 regclient 或所有 Registry 的通用默认值。

如果已经知道最小失败层的大小,将 blob-max 设置在该大小以下;如果 Registry 网关公布了请求体限制,则同时确保 blob-maxblob-chunk 低于该限制。

确认配置已保存,然后重新执行复制命令:

language-shell
regctl registry config "$DST_REGISTRY"

regctl image copy \
  --platform "$PLATFORM" \
  "$SRC_IMAGE" \
  "$DST_IMAGE"

复制完成后,按照验证目标摘要并试运行镜像检查结果。需要恢复该目标主机的默认 blob 上传策略时,清除显式配置:

language-shell
regctl registry set "$DST_REGISTRY" \
  --blob-max 0 \
  --blob-chunk 0

重要

分块上传不是跨进程断点续传

regctl 可以在同一个复制进程中重试分块请求。进程退出后重新运行时,目标端已经完整提交的镜像层通常可以复用,但未完整提交的单个层仍可能从头上传。

排查复制失败

第一个请求就返回 401 或 403

这类错误与单层大小无关。确认使用了目标可用区的正确公网地址,并检查账号是否具有目标 Repository 的推送权限。能够读取或列出镜像不表示能够推送。

无法同时连接源端和目标端

regctl 运行设备必须同时能够访问源 Registry 和目标 Registry。访问 Docker Hub 需要代理、而目标可用区 Registry 应当直连时,让 Docker Hub 及其镜像层下载域名走代理,并把目标 Registry 公网主机名加入 NO_PROXYNO_PROXY 中只填写主机名,不要包含 https:// 或路径。

不要通过关闭 TLS 校验绕过连接或证书错误。目标 Registry 公网地址应使用镜像中心提供的正式 HTTPS 入口。

分块请求仍然反复失败

按以下顺序检查:

  1. 确认 regctl registry config "$DST_REGISTRY" 显示预期的 blobMaxblobChunk
  2. 检查代理、VPN、网关和防火墙是否会重置长连接或拦截 PATCH 上传;
  3. 逐步减小 blobChunk,观察单次请求能否稳定完成;
  4. 确认目标 Registry 存储空间和租户配额充足;
  5. 如果目标 Registry 不接受分块上传,改用 Docker pulltagpush 流程,或联系平台支持确认 Registry 限制。

保存配置后的连通性探测不适用

regctl registry set 默认会在保存配置后检查 Registry 连通性。只有该额外探测已知不适用,或需要在 Registry 尚不可达时预写配置,才添加 --skip-check。该选项不参与镜像上传,也不能修复 TLS、认证或网络错误;真正复制时仍会发出 Registry 请求。

重新运行后仍从大层开头传输

分块重试主要发生在同一个 regctl 进程内。设备休眠、进程退出或上传会话过期后,未完整提交的单个层仍可能从头开始。长时间复制时,请在不会随终端关闭而退出的环境中运行,例如持久服务器的 tmux 会话或受控 CI Runner。

了解 regctl 的使用边界

  • regctl 不负责执行 Dockerfile、构建镜像或运行容器;
  • 分块上传不能修复错误凭证、权限不足、目标存储不足或不受支持的 Registry API;
  • --platform 会改变目标镜像包含的平台范围,需要保留完整多架构镜像时不要使用该选项。

查看官方参考和平台文档