docker - GitLab CI/CD : building multiarch Docker images

标签 docker build gitlab gitlab-ci multiarch

我想要一种在 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):

这是 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 .

  • 为什么?

    最佳答案

    不幸的是,有很多关于在 GitLab CI 上构建多架构镜像的过时和不正确的信息。似乎经常更改,因为它仍然是一个实验性功能。但截至本文发布之时,这就是我如何让我的多架构构建在 GitLab 公共(public)运行器(armv6、armv6、arm64、amd64)上工作:
    首先,必须构建并推送一个包含 buildx 的 Docker 镜像。二进制。这是我为此使用的 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
    所以我们必须在我们的管道中做到这一点。我们引用 MR 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

    关于docker - GitLab CI/CD : building multiarch Docker images,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61430005/

    相关文章:

    kubernetes - 为Kubernetes命名空间设置部署锁定?

    docker - 访问容器内的 Docker 套接字

    windows - 使用 Docker 在 Windows 上安装 gitlab

    python - 使用 Locust 对 docker-compose 应用程序进行性能测试时,连接被拒绝错误 (111)

    bash - 如何检测 docker run 和底层守护程序是否以编程方式完全启动?

    java - Gradle 构建通过 jenkins 花费的时间太长

    java - 作为 Maven 构建的一部分将字符串转换为 unicode

    tfs - 以编程方式获取TFS构建定义元数据

    git - 无法通过 aws ec2 上的 ssh 克隆 gitlab repo

    docker - Gitlab CI。来自守护进程 : No such image 的错误响应