You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Curl/JFrog CLI推送Docker镜像至Artifactory失败排查

问题描述

TLDR

尝试用Curl/JFrog CLI推送Docker镜像,但上传后的镜像损坏,无法正常拉取使用。

背景

由于网络连接限制,必须通过API网关访问公司的Artifactory Docker镜像仓库。Docker登录等命令无法正常工作,因为它尝试连接子域名(例如my-registry.public-domain.com)。可以通过Artifactory API使用Curl/JFrog CLI推送/拉取文件,目标是仅通过API将有效的Docker镜像推送到该Artifactory。

操作步骤

构建Docker镜像

docker build . --file Dockerfile -t helloworld:v1.1

将镜像保存为本地文件

docker image save --output=helloworld-v1.1.tar helloworld:v1.1

解压.tar镜像文件

mkdir v1.1; tar -xvf helloworld-v1.1.tar -C v1.1

上传各层文件及manifest.json至Artifactory

jfrog rt upload "v1.1/*" my-registry/helloworld/ --url xyz.com/artifactory --user foo --password bar

(上述命令相当于递归执行Curl PUT上传v1.1/目录下的所有内容)

结果

各层文件和manifest.json已上传至Artifactory,但出现异常:

  • Docker信息为空,提示:
    Unable to extract Docker metadata for
    'my-registry/helloworld/v1.1/'
    
  • 尝试从Openshift拉取镜像时出现以下错误(通过常规方式上传的镜像可正常拉取):
    Failed to pull image "my-registry.my-artifactory/helloworld:v1.1": rpc
    error: code = Unknown desc = pinging container registry
    l-docker-dev-workspace-dev.a-artifactory.vt.ch: invalid status code
    from registry 400 (Bad Request)
    

提问

请问该异常的原因是什么?如何将.tar格式的Docker镜像传输至Artifactory,使其能像其他镜像一样正常使用?


解决方案

异常原因

当前上传方式不符合Docker Registry API规范,Artifactory的Docker仓库需要遵循标准镜像结构与上传流程,具体问题点:

  1. 目录结构错误:docker save导出的tar包解压后是镜像原始层文件和manifest,但Artifactory Docker仓库需要按镜像名称、标签、摘要组织的层级结构,而非直接将解压文件放到helloworld/v1.1/下。
  2. 元数据关联错误:镜像的config.json引用路径不正确,manifest未正确关联到对应标签,Artifactory无法识别这是合法Docker镜像。
  3. 未触发元数据解析:直接上传文件不会触发Artifactory的Docker元数据提取流程,导致它无法识别镜像类型。

正确上传方法

方法1:使用JFrog CLI的Docker镜像上传功能(推荐)

JFrog CLI原生支持Docker镜像上传,无需手动解压tar包,自动遵循Docker Registry API规范:

# 配置JFrog CLI指向Artifactory实例
jfrog rt config --url="xyz.com/artifactory" --user="foo" --password="bar"

# 上传本地镜像到Artifactory Docker仓库
jfrog rt docker-push helloworld:v1.1 my-registry/helloworld:v1.1

若网络限制导致无法直接用Docker客户端连接,添加--local参数让JFrog CLI模拟Registry交互:

jfrog rt docker-push helloworld:v1.1 my-registry/helloworld:v1.1 --local

方法2:手动按Docker Registry规范上传

若必须用Curl操作,需遵循以下步骤:

  1. 提取镜像核心元数据:
    解压tar包后,查看manifest.json,找到Config字段对应的配置文件(如abc123.json),同时记录每个Layers字段中的层文件路径。
  2. 上传镜像配置文件:
    先计算配置文件的SHA256哈希值(用sha256sum v1.1/abc123.json获取),再上传:
    curl -u foo:bar -X PUT "xyz.com/artifactory/my-registry/v2/helloworld/blobs/sha256:<config-sha256>" --data-binary "@v1.1/abc123.json"
    
  3. 上传所有镜像层文件:
    对每个层文件计算SHA256哈希,然后上传:
    curl -u foo:bar -X PUT "xyz.com/artifactory/my-registry/v2/helloworld/blobs/sha256:<layer-sha256>" --data-binary "@v1.1/def456/layer.tar"
    
  4. 上传修正后的manifest:
    修改解压后的manifest.json,确保config和layers的digest字段对应已上传的SHA256值,然后上传到标签路径:
    curl -u foo:bar -X PUT "xyz.com/artifactory/my-registry/v2/helloworld/manifests/v1.1" -H "Content-Type: application/vnd.docker.distribution.manifest.v2+json" --data-binary "@modified-manifest.json"
    

方法3:通用仓库中转+Artifactory转换

  1. 将tar包上传到Artifactory通用本地仓库(如generic-repo):
    jfrog rt upload helloworld-v1.1.tar generic-repo/docker-images/
    
  2. 在Artifactory中配置匹配Docker结构的Repository Layout,通过Promote功能或REST API将tar包转换为Docker仓库中的合法镜像(需Artifactory具备对应权限与配置)。

验证

上传完成后,在Artifactory Docker仓库中查看helloworld:v1.1的镜像信息,确认元数据正常显示后,再尝试从Openshift拉取测试。


内容的提问来源于stack exchange,提问作者Don_Malocran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 13:17:59