构建基于多架构容器镜像

426 阅读5分钟

清单和清单列表(Manifests and manifest lists)

多架构镜像基于镜像的清单和清单列表

清单(Manifest)

每个容器镜像都由一个manifest表示。一个manifest是一个json 文件,唯一的标识一个镜像、镜像的layers和镜像的大小。

这是一个基于linux系统的基本的镜像清单

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": 1510,
    "digest": "sha256:fbf289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e"
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 977,
      "digest": "sha256:2c930d010525941c1d56ec53b97bd057a67ae1865eebf042686d2a2d18271ced"
    }
  ]
}

清单列表(Manifest list)

多架构镜像的清单列表(也通常称为OCI镜像的镜像索引)是一个镜像的集合(索引),我们可以指定一个或者多个镜像来创建一个清单列表。包括每个镜像的详细信息。例如支持的操作系统和系统架构,镜像大小和清单摘要等;我们可以像使用镜像一样来使用docker run , docker pull等命令来使用清单列表。

客户端使用docker manifest命令集来管理Manifest list。(现在docker manifest命令是实验性的,可以参考docker官方文档查看详细信息)

这是一个清单列表的样例

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
  "manifests": [
    {
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "size": 524,
      "digest": "sha256:83c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a",
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "size": 525,
      "digest": "sha256:873612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343",
      "platform": {
        "architecture": "arm64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "size": 1124,
      "digest": "sha256:b791ad98d505abb8c9618868fc43c74aa94d08f1d7afe37d19647c0030905cae",
      "platform": {
        "architecture": "amd64",
        "os": "windows",
        "os.version": "10.0.17763.1697"
      }
    }
  ]
}

多架构镜像

创建推送多架构镜像

当我们需要创建多架构镜像的时候,可以遵循以下步骤来创建并推送到指定镜像仓库。

  1. 为每个指定系统架构的镜像重新tag,并推送到镜像仓库;以下是linux系统amd64和arm64架构的两个基础镜像
# 重新tag arm64镜像
docker tag myimage:arm64 myregistry.azurecr.io/multi-arch-samples/myimage:arm64
# 推送到指定仓库
docker push myregistry.azurecr.io/multi-arch-samples/myimage:arm64

# 重新tag amd64镜像
docker tag myimage:amd64 myregistry.azurecr.io/multi-arch-samples/myimage:amd64
# 推送到指定仓库
docker push myregistry.azurecr.io/multi-arch-samples/myimage:amd64
  1. 通过docker manifest create命令创建一个多架构镜像的清单列表
# 创建多架构镜像清单列表
docker manifest create myregistry.azurecr.io/multi-arch-samples/myimage:multi \
 myregistry.azurecr.io/multi-arch-samples/myimage:arm64 \
 myregistry.azurecr.io/multi-arch-samples/myimage:amd64
  1. 通过docker manifest push命令将多架构镜像的清单列表推送到指定镜像仓库
# 推送多架构镜像清单列表 
docker manifest push myregistry.azurecr.io/multi-arch-samples/myimage:multi
  1. 使用docker manifest inspect命令查看清单列表详细信息
# 查看清单列表详细信息
docker manifest inspect myregistry.azurecr.io/multi-arch-samples/myimage:multi
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
  "manifests": [
    {
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "size": 524,
      "digest": "sha256:83c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a",
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "size": 525,
      "digest": "sha256:873612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343",
      "platform": {
        "architecture": "arm64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "size": 1124,
      "digest": "sha256:b791ad98d505abb8c9618868fc43c74aa94d08f1d7afe37d19647c0030905cae",
      "platform": {
        "architecture": "amd64",
        "os": "windows",
        "os.version": "10.0.17763.1697"
      }
    }
  ]
}

实际应用

构建基于linux系统的amd64和arm64架构的多架构JDK镜像,用于公司产品适配不同系统的架构。

步骤一

青云拉取amd64与arm64基础镜像

# 基于amd64的镜像
docker pull xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk-amd64

# 基于arm64的镜像
docker pull xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk-arm64

步骤二

将青云拉取下来的镜像重命名

docker tag xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk \ 
		xxx
docker tag xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk-amd64 \ 
		xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk-amd64

docker tag xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk-arm64 \ 
		xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk-arm64

步骤三

运行docker manifest create以创建清单列表,以将前面的镜像合并到多架构镜像中

docker manifest create xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk \
    xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk-amd64 \
    xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk-arm64 --amend

步骤四

推送多架构清单列表到新的镜像仓库

docker manifest push xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk

步骤五

查看多架构镜像清单列表详细信息

docker manifest inspect xxxx.xxx.xxxx/xxxx/openjdk:8u342-jdk

{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1795,
         "digest": "sha256:3af2ac94130765b73fc8f1b42ffc04f77996ed8210c297fcfa28ca880ff0a217",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1795,
         "digest": "sha256:53ff4b6f85a89d88a34a0e8a00f1df940d15aee8cc1c717f919cc368ece0218e",
         "platform": {
            "architecture": "arm64",
            "os": "linux",
            "variant": "v8"
         }
      }
   ]
}

参考文档

Multi-architecture images in your Azure container registry

如何保存/同步多架构容器 Docker 镜像

docker manifest