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

Cl0*_*ent 4 build gitlab docker 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
Run Code Online (Sandbox Code Playgroud)

问题是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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

那么发生了什么事?

  • 在构建结束时,我在 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.

为什么?

小智 6

不幸的是,关于在 GitLab CI 上构建多架构映像有很多过时和不正确的信息。由于它仍然是一个实验性功能,因此似乎经常发生变化。但截至本文发布时,这就是我如何在 GitLab 公共运行器(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
Run Code Online (Sandbox Code Playgroud)

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

所以我们必须在我们的管道中做到这一点。我们参考了 GitLab Runner 代码的MR 1861中的注释,并在我们的.gitlab-ci.yml.

before_script:
  - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes 
Run Code Online (Sandbox Code Playgroud)

然后我们可以使用docker logindocker buildx build --usedocker buildx build --push ...等等来运行我们的管道脚本的其余部分。

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


gdu*_*one 5

好吧,我我知道这里发生了什么:您需要调用update-binfmts --enable某个地方来启用 binfmt_misc 为 .

我能够使用此存储库及其 docker 图像在 gitlab-ci 上(经过大量搜索)获得与 buildx 一起使用的多架构图像:https ://gitlab.com/ericvh/docker-buildx-qemu

然而,该存储库对其自己的 docker 镜像存储库具有自依赖性,以构建自身的多架构版本,并且它的 ci 依赖于 gitlab-ci 模板存储库。我对这个依赖网络是如何开始的并不是非常有信心,并且该存储库的所有者比我熟练得多,但对于我的使用,我已经分叉了该存储库,现在我正在尝试将其 CI 修改为减少对外部资源的依赖。

编辑:对于来自未来的人来说,这是 Dockerfile:

FROM debian
# Install Docker and qemu
# TODO Use docker stable once it properly supports buildx
RUN apt-get update && apt-get install -y \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg2 \
        software-properties-common && \
    curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \
    add-apt-repository "deb https://download.docker.com/linux/debian $(lsb_release -cs) stable" && \
    apt-get update && apt-get install -y \
        docker-ce-cli \
        binfmt-support \
        qemu-user-static

# Install buildx plugin
RUN mkdir -p ~/.docker/cli-plugins && \
    ARCH=`dpkg --print-architecture` && echo Running on $ARCH && curl -s https://api.github.com/repos/docker/buildx/releases/latest | \
        grep "browser_download_url.*linux-$ARCH" | cut -d : -f 2,3 | tr -d \" | \
    xargs curl -L -o ~/.docker/cli-plugins/docker-buildx && \
    chmod a+x ~/.docker/cli-plugins/docker-buildx

# Write version file
RUN printf "$(docker --version | perl -pe 's/^.*\s(\d+\.\d+\.\d+.*),.*$/$1/')_$(docker buildx version | perl -pe 's/^.*v?(\d+\.\d+\.\d+).*$/$1/')" > /version && \
    cat /version
Run Code Online (Sandbox Code Playgroud)

以及 .gitlab-ci.yml 的精简版本

FROM debian
# Install Docker and qemu
# TODO Use docker stable once it properly supports buildx
RUN apt-get update && apt-get install -y \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg2 \
        software-properties-common && \
    curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \
    add-apt-repository "deb https://download.docker.com/linux/debian $(lsb_release -cs) stable" && \
    apt-get update && apt-get install -y \
        docker-ce-cli \
        binfmt-support \
        qemu-user-static

# Install buildx plugin
RUN mkdir -p ~/.docker/cli-plugins && \
    ARCH=`dpkg --print-architecture` && echo Running on $ARCH && curl -s https://api.github.com/repos/docker/buildx/releases/latest | \
        grep "browser_download_url.*linux-$ARCH" | cut -d : -f 2,3 | tr -d \" | \
    xargs curl -L -o ~/.docker/cli-plugins/docker-buildx && \
    chmod a+x ~/.docker/cli-plugins/docker-buildx

# Write version file
RUN printf "$(docker --version | perl -pe 's/^.*\s(\d+\.\d+\.\d+.*),.*$/$1/')_$(docker buildx version | perl -pe 's/^.*v?(\d+\.\d+\.\d+).*$/$1/')" > /version && \
    cat /version
Run Code Online (Sandbox Code Playgroud)

编辑:

此外,我发现使用上面构建的图像的 gitlabci 配置可以使用构建缓存:

build:
  image: docker:dind
  stage: build
  services:
    - name: docker:dind
      entrypoint: ["env", "-u", "DOCKER_HOST"]
      command: ["dockerd-entrypoint.sh"]
  variables:
    DOCKER_HOST: tcp://docker:2375/
    DOCKER_DRIVER: overlay2
    # See https://github.com/docker-library/docker/pull/166
    DOCKER_TLS_CERTDIR: ""
  before_script:
    - |
      if [[ -z "$CI_COMMIT_TAG" ]]; then
        export CI_APPLICATION_REPOSITORY=${CI_APPLICATION_REPOSITORY:-$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG}
        export CI_APPLICATION_TAG=${CI_APPLICATION_TAG:-$CI_COMMIT_SHA}
      else
        export CI_APPLICATION_REPOSITORY=${CI_APPLICATION_REPOSITORY:-$CI_REGISTRY_IMAGE}
        export CI_APPLICATION_TAG=${CI_APPLICATION_TAG:-$CI_COMMIT_TAG}
      fi
    - echo "$CI_REGISTRY_PASSWORD" | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
  script:
    - docker build -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" -t "$CI_APPLICATION_REPOSITORY:latest" .
    - docker push "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"  
    - docker push "$CI_APPLICATION_REPOSITORY:latest"
Run Code Online (Sandbox Code Playgroud)

  • Docker 有一篇博客文章,涵盖了 GitLab CI/CD 上的多架构构建 https://www.docker.com/blog/multi-arch-build-what-about-gitlab-ci/ (2认同)