GitLab CI/CD:构建多架构 Docker 镜像

2024-06-25

我想要一种在 GitLab 运行程序中构建多架构 Docker 映像的简单方法。简单地说,我的意思是我只需要在我的项目中添加一个 .gitlab-ci.yml 就可以了。

这是我写的 .gitlab-ci.yml。它使用 buildx 构建多架构镜像,然后将其推送到 GitLab 注册表:

image: cl00e9ment/buildx

services:
- name: docker:dind

variables:
  PLATFORMS: linux/amd64,linux/arm64
  TAG: latest

before_script:
  - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"

build:
  stage: build
  script:
  - docker buildx build --platform "$PLATFORMS" -t "${CI_REGISTRY_IMAGE}:${TAG}" . --push

问题是linux/arm64平台不可用。

以下是我构建 cl00e9ment/buildx 图像的方法(强烈的灵感来自snadn/docker-buildx https://gitlab.com/snadn/docker-buildx):

这是 Dockerfile:

FROM docker:latest

ENV DOCKER_CLI_EXPERIMENTAL=enabled
ENV DOCKER_HOST=tcp://docker:2375/

RUN mkdir -p ~/.docker/cli-plugins \
  && wget -qO- https://api.github.com/repos/docker/buildx/releases/latest | grep "browser_download_url.*linux-amd64" | cut -d : -f 2,3 | tr -d '"' | xargs wget -O ~/.docker/cli-plugins/docker-buildx \
  && chmod a+x ~/.docker/cli-plugins/docker-buildx
RUN docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
RUN docker context create buildx \
    && docker buildx create buildx --name mybuilder \
    && docker buildx use mybuilder
RUN docker buildx inspect --bootstrap

...这里添加的是用于构建和推送 cl00e9ment/buildx 映像的 .gitlab-ci.yml 文件:

image: docker:latest

services:
  - name: docker:dind

before_script:
  - docker login -u cl00e9ment -p "$DOCKER_HUB_TOKEN"

build:
  stage: build
  script:
  - docker build --add-host docker:`grep docker /etc/hosts | awk 'NR==1{print $1}'` --network host -t cl00e9ment/buildx .
  - docker run --add-host docker:`grep docker /etc/hosts | awk 'NR==1{print $1}'` --network host cl00e9ment/buildx docker buildx inspect --bootstrap
  - docker push cl00e9ment/buildx

test:
  stage: test
  script:
  - docker run --add-host docker:`grep docker /etc/hosts | awk 'NR==1{print $1}'` --network host cl00e9ment/buildx docker buildx inspect --bootstrap

那么发生了什么事?

  • 在构建结束时,在 Dockerfile 中,我运行docker buildx inspect --bootstrap列出可用的平台。它给linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6。所以一切都很好。
  • 之后,我再次运行它(就在构建之后和推送之前),它仍然给出linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6.
  • 然而,在测试阶段,当在干净的环境中从 Docker Hub 新鲜下载镜像时,它给出了linux/amd64, linux/386.

Why?


不幸的是,GitLab CI 上有很多关于构建多架构镜像的过时且不正确的信息。由于它仍然是一个实验性功能,因此似乎经常发生变化。但截至本文撰写时,我的多架构构建在 GitLab 公共运行器(armv6、armv6、arm64、amd64)上运行:

首先,必须构建并推送一个包含以下内容的 Docker 镜像:buildx二进制。这是我为此使用的 Dockerfile:

FROM docker:latest
ARG BUILDX_VER=0.4.2
RUN mkdir -p /root/.docker/cli-plugins && \
    wget -qO ~/.docker/cli-plugins/docker-buildx \
    https://github.com/docker/buildx/releases/download/v${BUILDX_VER}/buildx-v${BUILDX_VER}.linux-amd64 && \
    chmod +x /root/.docker/cli-plugins/docker-buildx

当前的 GitLab 运行器镜像未初始化binfmt尽管运行了初始化代码,但处理程序仍然正确:https://gitlab.com/gitlab-org/gitlab-runner/-/blob/523854c8/.gitlab/ci/_common.gitlab-ci.yml#L91 https://gitlab.com/gitlab-org/gitlab-runner/-/blob/523854c8/.gitlab/ci/_common.gitlab-ci.yml#L91

所以我们必须在我们的管道中做到这一点。我们参考了中的评论MR 1861 https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1861的 GitLab Runner 代码并将以下魔法酱添加到我们的.gitlab-ci.yml:

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

然后我们可以运行管道脚本的其余部分docker login, docker buildx build --use, docker buildx build --push ...等等。

现在,运行程序已准备好构建多种架构。 我的决赛.gitlab-ci.yml可以在这里看到:https://github.com/oofnikj/nuttssh/blob/multiarch/.gitlab-ci.yml https://github.com/oofnikj/nuttssh/blob/multiarch/.gitlab-ci.yml

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GitLab CI/CD:构建多架构 Docker 镜像 的相关文章

随机推荐