Loading... 省流:自 buildx 0.10 版本开始,就可能会出现这个问题,解决版本是 docker buildx 时增加参数 `--provenance=false`。 ## 问题复现 先来看示例,如有 `Dockerfile`: ``` FROM alpine RUN uname -a > /os.txt CMD cat /os.txt ``` 通过以下命令构建 `Multi-platform` 镜像: ```bash docker buildx create --driver docker-container --use docker buildx build --platform linux/amd64,linux/arm64 --push --tag zhaojun1998/buildx-demo:latest . ``` 推送后,通过 `docker manifest inspect zhaojun1998/buildx-demo:latest` 查看: ```json { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 668, "digest": "sha256:5a0b3d0151d5505f6ab6bf2f6824b2d8fdcfcd0ae7cf9f2403606c6fccaf27f2", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 668, "digest": "sha256:38da41f844e3bfae577f8b768b53a4980838bba97c6952aaae4debf3ea66cee7", "platform": { "architecture": "arm64", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 566, "digest": "sha256:6749a2e66b9e0e9cfc751e215e1036385c9cfd17e68bc8feca771381ce8ce806", "platform": { "architecture": "unknown", "os": "unknown" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 566, "digest": "sha256:f0b8829a483c98b1bc7fd0a8b16765fe5b29cca632a13db971c0c3749df09c3f", "platform": { "architecture": "unknown", "os": "unknown" } } ] } ``` 这里面有几个问题: 1. mediaType 版本为 `application/vnd.oci.image.index.v1+json`,最新版本为 v2。 2. 下面有两个 `platform.architecture` 与 `platform.os` 为 `unknown` 的数据项。 有些工具无法正常处理这种情况的镜像,如阿里的 [image-syncer](https://github.com/AliyunContainerService/image-syncer) ## 解决办法 构建命令中增加 `--provenance=false`: ```bash docker buildx build --provenance=false --platform linux/amd64,linux/arm64 --tag zhaojun1998/buildx-demo:no-provenance --push . ``` 然后再通过 `docker manifest inspect zhaojun1998/buildx-demo:no-provenance` 查看: ```json { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "manifests": [ { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 696, "digest": "sha256:c2f325142a90e152e0ea9eca07f5de281e183028da40991d5354b08da913da62", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 696, "digest": "sha256:8211d0f98a9a8a6f4b87826a2cb78ae375e76c2e5d6fbaaee46709f9f422022d", "platform": { "architecture": "arm64", "os": "linux" } } ] } ``` 现在可以发现,上面的两个问题已经解决了。 ## 已有镜像修复 上面的可以在新推送镜像时避免产生问题,但是对于已有镜像有时候不方便重新制作,可以通过以下办法修复已有镜像: ### 去除 unknown 部分 可以用以下脚本 `fix-image.sh` 来解决: ``` #!/bin/bash set -v set -e # 检查是否提供了镜像地址 if [ -z "$1" ]; then echo "请提供镜像地址" exit 1 fi IMAGE=$1 # 获取镜像的 manifest MANIFEST=$(docker manifest inspect $IMAGE) # 检查是否成功获取 manifest if [ $? -ne 0 ]; then echo "获取 manifest 失败" exit 1 fi echo "获取到 manifest 为: $MANIFEST" # 解析 manifest,移除 architecture 或 os 为 unknown 的条目 FILTERED_MANIFEST=$(echo $MANIFEST | jq 'del(.manifests[] | select(.platform.architecture == "unknown" or .platform.os == "unknown"))') echo "过滤后 manifest 为: $FILTERED_MANIFEST" # 检查是否有剩余的条目 if [ $(echo $FILTERED_MANIFEST | jq '.manifests | length') -eq 0 ]; then echo "过滤后没有剩余的条目,退出" exit 1 fi # 提取剩余条目的 digest DIGESTS=$(echo $FILTERED_MANIFEST | jq -r '.manifests[].digest') # 准备 docker manifest create 命令 NEW_IMAGE="${IMAGE}" # 这里可以自行决定修复后的镜像是否和原来的 tag 一样,如增加 -fix CREATE_CMD="docker manifest create $NEW_IMAGE" for DIGEST in $DIGESTS; do CREATE_CMD="$CREATE_CMD --amend ${IMAGE%%:*}@$DIGEST" done # 执行 docker manifest create 命令 eval $CREATE_CMD # 推送新的 manifest docker manifest push $NEW_IMAGE echo "新的 manifest 已创建并推送: $NEW_IMAGE" ``` 使用办法为 `./fix-image.sh zhaojun1998/buildx-demo:latest`,可以看到修复后的 manifest 变为了: ```json { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 668, "digest": "sha256:d756e0a11dd550bb5ea6affd46352119aee6f16981fa588667c54929efa95589", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 668, "digest": "sha256:ef6cd7110abcd9eb9c1c402e46c6de4de6138e5e0ef6f7b84b81a56d64b84212", "platform": { "architecture": "arm64", "os": "linux" } } ] } ``` ## 升级镜像规范版本 根据自己的系统架构安装 [regctl](https://github.com/regclient/regclient/releases),然后执行命令: ```bash regctl image mod zhaojun1998/buildx-demo:latest --to-docker --replace ``` 再查看 `manifest` 为: ```json { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "manifests": [ { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 587, "digest": "sha256:89d1d24005f61c825f1e07d819ce52c71c0c4ba96d7457d9b9f40dde59c31c78", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 587, "digest": "sha256:c1cd468c5476d0c33ca877a0dce7871d55550fdfbc00466f450f3bf63e5ea8ac", "platform": { "architecture": "arm64", "os": "linux" } } ] } ``` ## 参考 - https://github.com/docker/buildx/issues/1507 - https://github.com/docker/buildx/issues/1509#issuecomment-1378454396 - https://github.com/docker/buildx/issues/1964#issuecomment-1644634461 - https://stackoverflow.com/questions/75692640/modify-docker-image-with-older-manifest-format 最后修改:2024 年 10 月 08 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请我喝杯咖啡吧。