我的项目有一个 私有 Gitlab 实例和几个私有 Google e2 运行器(amd64 架构)。
除了基本配置之外,e2 运行器还配置为使用主机 docker 守护进程运行 docker 作业。这是我如何实现这一目标的示例配置(来自一些教程)
concurrent = 1
check_interval = 0
...
[[runners]]
...
executor = "docker"
[runners.docker]
tls_verify = false
image = "alpine"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache", "/certs/client", "/builds:/builds"]
shm_size = 0
wait_for_services_timeout=120
network_mode = "host"
现在,我有一个 CI 管道可以:
someimage:{ref}-temp
someimage:{ref}
并将其推送到存储库当此管道在 e2 运行器上运行时,一切都很好,并且生成的图像可在任何 amd64 linux 或 windows 计算机上使用。
但是,我注册了一个Rapsberry Pi 4作为附加的gitlab-runnger(arm64架构),管道运行成功,但生成了无法使用的图像。当我尝试运行它们时,它说图像架构与主机不匹配。显然,图像在 Pi 上运行得很好,但我无法让它们在 amd64 的产品服务器上运行。
我尝试使用
docker buildx bake
和 .hcl 文件来定义目标映像的架构,它确实有效,但 CI 管道失败了,因为它确实生成了 amd64 跨架构映像,但无法运行集成在 Pi 上进行测试(由于架构不匹配,无法启动图像)。
所以,我想解决方案是:
someimage:{ref}-temp-amd64
和 someimage:{ref}-temp-arm64
someimage:{ref}
但是,我想知道是否有更优雅的解决方案。我想避免在项目代码中引入复杂的构建命令和配置。例如。是否可以专门配置 Pi 运行器以在整个管道中模拟 amd64 架构?不幸的是,我对 docker emulation 不是很熟悉。
感谢您提前提供的任何帮助!
您可以使用 docker buildx --platform 在目标架构上构建镜像 并使用 docker multistage build 来构建镜像,以进行编译、测试和构建目标镜像
在第一阶段将所有内容构建到目标目录(又名/build),在其他阶段复制该内容以在测试中使用并在最终图像中使用
类似 Dockerfile 中的内容:
FROM alpine:latest as build
RUN set -ex; \
mkdir -p /build ; \
echo "arch: $(uname -m)" > /build/result.log
FROM alpine:latest as test
COPY --from=build /build/ /
RUN set -eux ;\
if [ "$(sed -n 's/^arch: \(.*\)$/\1/p;' /result.log)" == "x86_64" ];then \
echo "Arch is OK!" ; \
else \
echo "Arch is Bad!" ; \
exit 1 ; \
fi
FROM alpine:latest
COPY --from=build /build/ /
因此,如果跑步者拱门是 amd64(x86_64),您将收到根目录中带有 result.log
的图像