繁体   English   中英

Docker 多平台在 Gitlab CI 上为 ARM64 构建极其缓慢

[英]Docker multi platform builds extremely slow for ARM64 on Gitlab CI

对于 Node.js 申请,我有以下 dockerfile

# ---> Build stage
FROM node:18-bullseye as node-build

ENV NODE_ENV=production
WORKDIR /usr/src/app
COPY . /usr/src/app/
RUN yarn install --silent --production=true --frozen-lockfile
RUN yarn build --silent

# ---> Serve stage
FROM nginx:stable-alpine
COPY --from=node-build /usr/src/app/dist /usr/share/nginx/html

到目前为止,我一直专门为 AMD64 构建,但现在我还需要为 ARM64 构建。

我将 my.gitlab-ci.yml 编辑为如下所示

image: docker:20

variables:
    PROJECT_NAME: "project"
    BRANCH_NAME: "main"
    IMAGE_NAME: "$PROJECT_NAME:$CI_COMMIT_TAG"

services:
    - docker:20-dind

build_image:
    script:
      # Push to Gitlab registry
      - docker login $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
      - docker context create builder-context
      - docker buildx create --name builderx --driver docker-container --use builder-context
      - docker buildx build --tag $CI_REGISTRY/mygroup/$PROJECT_NAME/$IMAGE_NAME --push --platform=linux/arm64/v8,linux/amd64 .

对于 AMD64,一切都相对良好,但对于 ARM64 却非常慢。 几乎比 AMD64 慢 10 倍,让我在 Gitlab 作业上超时。

有什么办法可以加快这个过程吗?

我猜您的管道正在 amd64 硬件上执行,而docker buildx正在执行仿真以构建 arm64 目标。 如果将build_image分成两个作业(一个用于 amd64,一个用于 arm64),然后将它们发送到两个不同的 gitlab 运行器,以便它们每个都可以在其本机硬件上执行,您可能会看到很大的改进。

即使您不能或不想停止使用仿真,您仍然可以将build_image作业分成两个作业(每个构建的图像一个),希望并行运行它们将使作业在超时限制之前完成。

通过更改您的 Dockerfile 和使用图像缓存,您可以使您的一些后续构建更快,但是在您构建初始图像(可用作缓存)之前,这些更改对您没有帮助。

更新Dockerfile

# ---> Build stage
FROM node:18-bullseye as node-build

ENV NODE_ENV=production
WORKDIR /usr/src/app
# only COPY yarn.lock so not to break cache if dependencies have not changed
COPY . /usr/src/app/yarn.lock 
RUN yarn install --silent --production=true --frozen-lockfile
# once the dependencies are installed, then copy in the frequently changing source code files
COPY . /usr/src/app/
RUN yarn build --silent

# ---> Serve stage
FROM nginx:stable-alpine
COPY --from=node-build /usr/src/app/dist /usr/share/nginx/html

更新gitlab-ci.yml

image: docker:20

variables:
    PROJECT_NAME: "project"
    BRANCH_NAME: "main"
    IMAGE_NAME: "$PROJECT_NAME:$CI_COMMIT_TAG"
    REGISTRY_IMAGE_NAME: "$CI_REGISTRY/mygroup/$PROJECT_NAME/$IMAGE_NAME"
    CACHE_IMAGE_NAME: "$CI_REGISTRY/mygroup/$PROJECT_NAME/$PROJECT_NAME:cache"
    BUILDKIT_INLINE_CACHE: "1"

services:
    - docker:20-dind

stages:
   - build
   - push

before_script:
   - docker login $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
   - docker context create builder-context
   - docker buildx create --name builderx --driver docker-container --use builder-context

build_amd64:
    stage: build
    script:
      - docker buildx build --cache-from "$CACHE_IMAGE_NAME" --tag "$CACHE_IMAGE_NAME"  --push --platform=linux/amd64 .

build_arm64:
    stage: build
    script:
      - docker buildx build --cache-from "$CACHE_IMAGE_NAME" --tag "$CACHE_IMAGE_NAME"  --push --platform=linux/arm64/v8 .

push:
   stage: push
   script: 
     - docker buildx build --cache-from "$CACHE_IMAGE_NAME" --tag "$REGISTRY_IMAGE_NAME"  --push --platform=linux/arm64/v8,linux/amd64 .

build_amd64build_arm64作业分别拉取最后构建的(其 arch 的)图像,并将其用作 docker 个图像层的缓存。 这两个构建作业然后将它们的结果作为新缓存推送回来。

push阶段再次运行docker buildx... ,但它们实际上不会构建任何新内容,因为它们只会从两个构建作业中提取缓存结果。 这允许您分解构建,但仍然有一个单一的推送命令,该命令导致两个不同的图像最终出现在一个多平台 docker 清单中。

我在 Google Cloud Build 上运行构建缓慢的问题,最终使用原生arm64硬件来加速构建的arm64部分。

我为此写了一个详细的教程,它使用 Docker 上下文指向远程arm64 VM。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM