构建并推送多架构docker映像

时间:2018-07-18 11:16:02

标签: macos docker raspbian

我正在尝试基于可在Raspbian和Mac OS X / Debian上使用的官方postgres图像制作自定义图像。

当我做一个

from postgres:10.4并构建Dockerfile,看来docker隐式选择了x64版本的postgres,然后仅基于该架构构建了一个新映像。

结果是,当我将图像推送到我的GitLab注册表并再次下载时,它不起作用。它抛出了standard_init_linux.go:190: exec user process caused "exec format error",我认为这是错误的体系结构的另一种说法。

据我在https://blog.docker.com/2017/09/docker-official-images-now-multi-platform/的了解,在一幅图像中支持多种架构使其成为“多重拱门”。但是,尽管有很多资源,但是我对如何构建自己的多拱形图像以及要求有什么印象并不明显。

理想情况下,我希望能够从Raspberry Pi / Raspbian主机和Mac / Debian主机无缝构建和推送armv7和x64版本。

我发现了这个问题:Cross-compile multi-arch containers

答案之一是一个过程。但是,该过程将不支持使用RUN命令的dockerfile,这是我的项目所必需的。

1 个答案:

答案 0 :(得分:5)

您需要为特定体系结构构建每个映像,然后生成清单,其中是每个映像的列表。第二部分的命令目前处于试验阶段。 documentation shows this example(尽管大多数人倾向于将架构放在标签名称中,例如myrepo/myapp:arm-linux-v1):

$ docker manifest create 45.55.81.106:5000/coolapp:v1 \
    45.55.81.106:5000/coolapp-ppc64le-linux:v1 \
    45.55.81.106:5000/coolapp-arm-linux:v1 \
    45.55.81.106:5000/coolapp-amd64-linux:v1 \
    45.55.81.106:5000/coolapp-amd64-windows:v1
Created manifest list 45.55.81.106:5000/coolapp:v1

$ docker manifest annotate 45.55.81.106:5000/coolapp:v1 45.55.81.106:5000/coolapp-arm-linux --arch arm

$ docker manifest push 45.55.81.106:5000/coolapp:v1
Pushed manifest 45.55.81.106:5000/coolapp@sha256:9701edc932223a66e49dd6c894a11db8c2cf4eccd1414f1ec105a623bf16b426 with digest: sha256:f67dcc5fc786f04f0743abfe0ee5dae9bd8caf8efa6c8144f7f2a43889dc513b
Pushed manifest 45.55.81.106:5000/coolapp@sha256:f3b3b28a45160805bb16542c9531888519430e9e6d6ffc09d72261b0d26ff74f with digest: sha256:b64ca0b60356a30971f098c92200b1271257f100a55b351e6bbe985638352f3a
Pushed manifest 45.55.81.106:5000/coolapp@sha256:39dc41c658cf25f33681a41310372f02728925a54aac3598310bfb1770615fc9 with digest: sha256:df436846483aff62bad830b730a0d3b77731bcf98ba5e470a8bbb8e9e346e4e8
Pushed manifest 45.55.81.106:5000/coolapp@sha256:f91b1145cd4ac800b28122313ae9e88ac340bb3f1e3a4cd3e59a3648650f3275 with digest: sha256:5bb8e50aa2edd408bdf3ddf61efb7338ff34a07b762992c9432f1c02fc0e5e62
sha256:050b213d49d7673ba35014f21454c573dcbec75254a08f4a7c34f66a47c06aba

要将docker客户端配置为具有实验性功能,可以在本地$HOME/.docker/config.json中设置以下内容:

{
   "auths": { ... },
   "experimental": "enabled"
}

在上面请注意,如果您执行了docker登录,则auths部分可能已经配置。除了在右括号后添加逗号外,您应保持该部分不变。如果您没有auths部分,请将该行从文件中排除。


  

但是,该过程将不使用RUN命令支持dockerfile,这是我的项目所必需的。

您可以下载用于不同体系结构的映像,但是您将无法从错误的体系结构运行这些映像。 RUN命令在构建过程中产生一个临时容器来运行所请求的命令,而该命令将根本无法工作。我知道为另一个体系结构提取映像的唯一原因是将该映像中继到可以使用它们的另一个位置(私有注册表或export + scp),或用于构建多体系结构清单,如您在上面看到的。 >


  

此处的要点是在单个主机上构建多个体系结构。我已经看到了使用QEMU实现此目的的博客文章,但是对于每种体系结构,它们都使用不同的基本图像。当基本映像已经是多体系结构映像时,尚不清楚如何执行此操作。

如果您可以不使用任何RUN步骤来构建图像,而是使用交叉编译器来处理图像之外的任何二进制文件,并且仅执行诸如COPY之类的步骤以将文件添加到新图像中,那么您可以在单个主机上创建所有内容。当上游映像是多体系结构时,您需要更深入地挖掘并找到特定于平台的标签以用于上游映像。有几种选择。困难的选择是检查multi-arch标记的清单以查看特定摘要:

$ docker manifest inspect busybox
{                    
   "schemaVersion": 2,                                                                       
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [                     
      {                  
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 527,
         "digest": "sha256:bbb143159af9eabdf45511fd5aab4fd2475d4c0e7fd4a5e154b98e838488e510",
         "platform": {                                                       
            "architecture": "amd64",
            "os": "linux"                                                                    
         }            
      },                            
      {                  
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 527,
         "digest": "sha256:3d1b11fb001ece2e99556690ce064b07851649582b1f0907649c21e65ba4298f",
         "platform": {
            "architecture": "arm",                                                                                                           
            "os": "linux",                                                                           
            "variant": "v5"
         }                                                                     
      },
...

然后,您可以使用特定的摘要标记,例如busybox@sha256:3d1b11fb001ece2e99556690ce064b07851649582b1f0907649c21e65ba4298f。为此,您可以使用jq解析输出:

docker manifest inspect busybox | \
  jq '.manifests | .[] | select(.platform.architecture == "arm64") | .digest'

但是,大多数多体系结构映像都包含用于单个体系结构的标签。因此,您将选择该特定标签而不是多体系结构标签。对于官方映像,docker当前具有特定于体系结构的存储库documented in their official images repo