我们都喜欢 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 镜像。
任何声称拥有特定 Docker 分发镜像规范(这很容易检查)支持的注册表或运行时,都将与各种 manifest 类型进行交互,以查找镜像内的以下内容:
构建容器根文件系统所需的实际文件系统内容(层)。
任何必要的特定镜像配置,以便了解如何运行容器,有些比其他更专业,用于使用特定的镜像。例如,类似于在启动容器时要运行的命令的信息(如构建镜像时使用的 Dockerfile 中所示)。
简而言之,Docker 容器 manifest 是一个包含容器镜像信息的文件。具体来说,包括 `digest`、`sha256`,最重要的是 arch。我们可以创建一个 manifest,它指向不同架构的镜像,以便在特定架构上使用镜像时,Docker 会自动拉取所需的镜像。
对此的一个很好的可视化表示是:
以下是仓库中的 ` .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 后,将其添加到您的 ` .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 仓库。
构建愉快!