问题描述
一些开发人员最近获得了一些 M1 机器,我想为他们提供 ARM 兼容的镜像,并且我已经开始尝试使用 Buildkit。我在 Jenkins 中设置了一个 podTemplate,并使用以下命令运行构建:
buildctl build --opt platform=linux/arm64 --frontend=dockerfile.v0 --local context=. --opt build-arg:HTTP_PROXY=http://proxy-here:8080 --opt build-arg:HTTPS_PROXY=http://proxy-here:8080 --local dockerfile=. --output type=image,push=true,"name=$BUILD_TAG,$SHORT_TAG,$MINOR_TAG,$FULL_TAG"
当针对 linux/amd64
架构构建时,一切都如计划进行,然而对于 linux/arm64
架构,会因 Dockerfile 中的不同原因而失败,例如:
RUN update-ca-certificates: Error while loading /usr/bin/run-parts: No such file or directory
我已经确认了 run-parts
存在,并且链接到了具有正确架构的 musl 库。
这个错误似乎表明它并没有在正确的 $PATH
下运行,但是 which
命令似乎能够找到这些命令,/lib/ld-musl-aarch64.so.1
也明确存在。
这个错误会发生在各种其他本来很普通的命令上,比如 ls
、addgroup
(但不包括 deluser
)。
我尝试过将 /bin/
目录中的文件链接到 /usr/bin/
,但这似乎是一场无休止的游戏,对我来说这种方法有点太 hack。
容器的基础镜像是 php:7.4.28-fpm-alpine
。我在这里完全搜索无果,我究竟做错了什么?
解决方案
请注意以下操作可能涉及版本差异或具有一定风险,建议谨慎操作。
方案1
根据你的问题描述,这个问题可能是因为在 ARM 架构上执行时,一些命令无法找到正确的库文件。你可以尝试使用 QEMU 进行模拟,以便在构建过程中解决这个问题。以下是如何在构建过程中添加 QEMU 模拟的步骤:
- 修改你的 podTemplate,添加一个 init container 来安装所需的 QEMU 模拟器。
spec: | |
initContainers: | |
- name: prepare | |
image: tonistiigi/binfmt:latest | |
args: ["--install", "arm64"] | |
securityContext: | |
privileged: true |
在上面的示例中,我们添加了一个名为 prepare
的 init container,使用了 tonistiigi/binfmt 镜像,这将安装所需的 QEMU 模拟器。这可以帮助 Buildkit 在构建 ARM 架构镜像时正确执行命令。
方案2
如果方案1不能解决问题,你还可以尝试调整 Dockerfile 中的一些命令,以确保在 ARM 架构上正确运行。可能需要修改一些特定于架构的命令,以适应 ARM 架构的特性。这需要根据你的具体 Dockerfile 进行调整,可能涉及到一些命令的替换或调整。
方案3
如果以上方案仍然无法解决问题,建议在相关社区寻求帮助,特别是 Buildkit 或 Docker 的官方论坛。可能有其他用户也遇到了类似的问题,或者社区的开发人员能够提供更详细的解决方案。
希望这些解决方案对你有帮助。如果问题仍然存在,建议进一步调查 Dockerfile 中命令的 ARM 兼容性,并尝试查找 Buildkit 的文档或其他资源,以找到更具体的解决方案。