使用多架构 Docker 镜像将 Docker Manifest 推送到单个仓库

分享
分享

我们都喜欢 Docker,它也是许多构建者的工具带之一。Docker 允许您拥有具有特定依赖项的隔离容器,因此“我不知道它在我的机器上是否有效”这句话现在已经不再出现,但如果您在 Raspberry Pi 或 Arduino 等 `Arm32` 设备上,却拉取了一个原本针对 `x64` 架构的镜像,会发生什么呢?(它将无法工作。)如果仓库能识别这一点,并根据您的主机操作系统将您路由到适合您架构的正确 Docker 镜像,那岂不是太好了吗?让我们来探索一下 Docker Manifest。

我们有时需要多架构镜像

在使用 Docker 时,您可能曾经有意或无意地尝试从一个并非您想要拉取的、针对其他架构的 Docker 镜像启动容器。

使用多架构镜像,我们可以快速查看哪些有效,哪些无效。为了测试这一点,个人认为,在推动 manifest 时,您应该始终使用 `-asm` 进行提交,以便在提交时签署,而不是使用通常的 `git commit -m "whatever"` 命令,而是使用 `git commit -asm "whatever"`。在这个我整理的特定示例中,我从 DockerHub 中获取了以下软件包

lucashalbert/curl
ppc64le/node
s390x/python  
ibmjava:jre 

这些是完美的软件包(cURL)、(ppc64le)、(s390x)、(ibmjava:jre),它们展示了使用 ppc64le、s390x 以及 manifest 的多架构 Docker 镜像。

为什么我需要使用 manifest

任何声称拥有特定 Docker 分发镜像规范(这很容易检查)支持的注册表或运行时,都将与各种 manifest 类型进行交互,以查找镜像内的以下内容:

构建容器根文件系统所需的实际文件系统内容(层)。

任何必要的特定镜像配置,以便了解如何运行容器,有些比其他更专业,用于使用特定的镜像。例如,类似于在启动容器时要运行的命令的信息(如构建镜像时使用的 Dockerfile 中所示)。

简而言之,Docker 容器 manifest 是一个包含容器镜像信息的文件。具体来说,包括 `digest`、`sha256`,最重要的是 arch。我们可以创建一个 manifest,它指向不同架构的镜像,以便在特定架构上使用镜像时,Docker 会自动拉取所需的镜像。

对此的一个很好的可视化表示是:

在使用 Docker Manifest 的同时使用 Travis

以下是仓库中的 ` .travis.yml` 文件,它也使用了我编写的 travis.sh bash 脚本,用于完成一些环境变量任务,同时推送到为该用例创建的自定义 ` .travis.yml` 文件。

---
language: shell # Montana Mendy also recommends generic, as an option here
sudo: required
dist: xenial
os: linux

services:
  - docker

addons:
  apt:
    packages:
      - docker-ce

env:
  - DEPLOY=false repo=ibmjava:jre docker_archs="amd64 ppc64le s390x"

install:
  - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

before_script:
  - export ver=$(curl -s "https://pkgs.alpinelinux.org/package/edge/main/x86_64/curl" | grep -A3 Version | grep href | sed 's/<[^>]*>//g' | tr -d " ")
  - export build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
  - export vcs_ref=$(git rev-parse --short HEAD)

  # Montana's crucial workaround
  
script:
  - chmod u+x ./travis.sh
  - chmod u+x /build.sh
  - export DOCKER_CLI_EXPERIMENTAL=enabled # crucial to use manifest

after_success:
  - docker images
  - docker manifest inspect --verbose lucashalbert/curl # multiarch build
  - docker manifest inspect --insecure lucashalbert/curl # multiarch build 
  - docker manifest inspect --verbose ppc64le/node # IBM power build 
  - docker manifest inspect --insecure ppc64le/node # IBM power build 
  - docker manifest inspect --verbose s390x/python # IBM Z build 
  - docker manifest inspect --insecure s390x/python # IBM z build
  - docker manifest inspect --verbose ibmjava:jre # official Docker IBM Java (Multiarch) build
  - docker manifest inspect --insecure ibmjava:jre # official Docker IBM Java (Multiarch) build

branches:
  only:
    - master
  except:
    - /^*-v[0-9]/
    - /^v\d.*$/

查看 Manifest

添加 manifest 后,将其添加到您的 ` .travis.yml` 中至关重要

script: export DOCKER_CLI_EXPERIMENTAL=enabled

或者,您也可以通过以下方式在项目的目录树中运行:

export DOCKER_CLI_EXPERIMENTAL=enabled

如您所见,通过结合使用特定于架构的标签和相关的 Docker manifest,我们可以从仓库中实现一种一劳永逸的、与架构无关的镜像拉取方式。在 Travis 构建您的项目时,您将开始看到您的 manifest,它看起来像这样:

运行 `docker manifest`

manifest 的每一层都包含一个 JSON 文件(看起来像我们之前提到的 .config 文件)、一个包含字符串 1.0 的 VERSION 文件,以及一个包含镜像文件的 layer.tar 文件。在这个特定情况下,我们将使用 VMWare 在我的 Ubuntu VM 中检查来自 DockerHub 的 ppc64le/node。

如果在 Ubuntu 上进行 manifest 操作,您可能需要解决一些依赖项,这相当容易

sudo apt install ruby-dev libffi-dev make gcc
sudo gem install travis

然后确保 Travis 已安装

which travis

然后您就可以开始了,现在让我们继续推送 manifest

"schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 945,
         "digest": "sha256:2ab48cb5665bebc392e27628bb49397853ecb1472ecd5ee8151d5ff7ab86e68d",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1363,
         "digest": "sha256:956f5cf1146bb6bb33d047e1111c8e887d707dde373c9a650b308a8ea7b40fa7",
         "platform": {
            "architecture": "arm",
            "os": "linux",
            "variant": "v6"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1363,
         "digest": "sha256:c6cc369f9824b7f6a19cca9d7f1789836528dd7096cdb4d1fc0922fd43af9d79",
         "platform": {
            "architecture": "arm",
            "os": "linux",
            "variant": "v7"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1363,
         "digest": "sha256:b9ae5a5f88f9e4f35c5ad8f83fbb0705cf4a38208a4e40c932d7abd2e7b7c40b",
         "platform": {
            "architecture": "arm64",
            "os": "linux",
            "variant": "v8"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1363,
         "digest": "sha256:4eca7b4f398526c8bf84be21f6c2c218119ed90a0ffa980dd4ba31ab50ca8cc5",
         "platform": {
            "architecture": "386",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1363,
         "digest": "sha256:2239e5d3ee0e032514fe9c227c90cc5a1980a4c12602f683f4d0a647fb092797",
         "platform": {
            "architecture": "ppc64le",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1363,
         "digest": "sha256:57523d3964bc9ee43ea5f644ad821838abd4ad1617eed34152ee361d538bfa3a",
         "platform": {
            "architecture": "s390x",
            "os": "linux"
         }
      }
   ]
}
Done. Your build exited with 0.

结论

虽然这种机制功能强大,但它仍然被认为是“实验性的”,目前只能从 CLI 进行操作,但使用 Travis,您可以将其集成到您的构建中,使操作变得简单一些。

如果您有任何问题,请发送邮件至 [email protected]。要更深入地了解此内容,请访问我的 名为“manifests”的 GitHub 仓库

构建愉快!

© 版权所有 2024 年,保留所有权利
© 版权所有 2024 年,保留所有权利
© 版权所有 2024 年,保留所有权利