使用Golang SDK上传本地Docker镜像到AWS ECR如何生成ImageManifest
构造ImageManifest参数及完整推送流程
要将本地Docker镜像通过AWS Go SDK推送至ECR,不能直接仅调用PutImage接口,你需要先完成镜像层、镜像配置的上传,再构造符合规范的Manifest参数,具体流程如下:
步骤1:获取本地镜像的基础信息
首先获取本地example:v1镜像的Manifest结构,可选两种方式:
- 命令行导出:执行
docker manifest inspect example:v1直接拿到符合Docker V2 Schema 2/OCI规范的Manifest JSON内容 - 代码读取:使用Docker官方Go SDK直接读取本地Docker daemon中的镜像Manifest信息
步骤2:完成前置资源上传
PutImage要求Manifest中引用的所有镜像配置、镜像层都已经提前上传到对应ECR仓库,否则会返回校验失败错误:
- 调用
PutImageLayer接口上传镜像配置JSON文件,获取配置的SHA256摘要 - 对每个镜像层,依次调用
InitiateLayerUpload、UploadLayerPart、CompleteLayerUpload接口完成上传,获取每个层的SHA256摘要
步骤3:构造ImageManifest参数
按照OCI/Docker V2 Schema 2规范构造Manifest JSON字符串,再转为AWS *string类型传入即可,完整代码示例如下:
package main import ( "encoding/json" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ecr" ) // DockerV2Manifest 符合Docker V2 Schema 2规范的Manifest结构 type DockerV2Manifest struct { SchemaVersion int `json:"schemaVersion"` MediaType string `json:"mediaType"` Config ECRManifestDescriptor `json:"config"` Layers []ECRManifestDescriptor `json:"layers"` } type ECRManifestDescriptor struct { MediaType string `json:"mediaType"` Size int64 `json:"size"` Digest string `json:"digest"` } func main() { mySession := session.Must(session.NewSession(&aws.Config{ Region: aws.String("<你的ECR所在区域>"), Credentials: credentials.NewStaticCredentials("<你的AccessKey>", "<你的SecretKey>", ""), })) ecrClient := ecr.New(mySession) // 这里替换为你上传完成后生成的配置和层信息 manifest := DockerV2Manifest{ SchemaVersion: 2, MediaType: "application/vnd.docker.distribution.manifest.v2+json", Config: ECRManifestDescriptor{ MediaType: "application/vnd.docker.container.image.v1+json", Size: <你的镜像配置文件大小>, Digest: "<你上传的镜像配置SHA256摘要>", }, Layers: []ECRManifestDescriptor{ { MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", Size: <镜像层1大小>, Digest: "<镜像层1的SHA256摘要>", }, // 按实际情况追加所有镜像层的信息 }, } // 序列化为JSON字符串 manifestBytes, err := json.Marshal(manifest) if err != nil { panic(err) } manifestStr := string(manifestBytes) // 调用PutImage接口 _, err = ecrClient.PutImage(&ecr.PutImageInput{ ImageManifest: aws.String(manifestStr), RepositoryName: aws.String("<你的ECR仓库名,注意不要填完整URI>"), ImageTag: aws.String("v1"), // 可选参数,给推送的镜像打标签 }) if err != nil { panic(err) } }
简便方案(无需手动构造Manifest)
如果不想自己处理层上传、Manifest校验等复杂逻辑,可以直接使用开源镜像操作库处理对接逻辑,库会自动完成所有上传、Manifest构造、校验流程。
注意事项
- 请确保你的访问凭证拥有
ecr:PutImage、ecr:InitiateLayerUpload、ecr:UploadLayerPart、ecr:CompleteLayerUpload、ecr:PutImageLayer相关权限 - Manifest中所有配置、层的摘要和大小必须和你上传到ECR的内容完全一致,否则会推送失败
RepositoryName参数仅需要填写仓库名称,不需要带账号ID、区域等前缀的完整URI
内容的提问来源于stack exchange,提问作者Keval Bhogayata
相关产品推荐
相关产品推荐

