我正在try 使用基于ARM的机器(具体地说,是arm.xlarge)在CircleCI上构建一个Next.js项目,该机器有32 GB的RAM.然而,它似乎很快就退出了,并出现了关于内存不足的错误.我try 将Node进程的内存一直增加到机器的内存,但没有成功--我收到了同样的错误.

特别奇怪的是,GC的内存使用率很小(3.5MB),并且它在亚秒级时间内退出!

如果我将arm资源类型替换为x86_64资源类型,并为x86_64平台构建一个Docker映像,则此构建确实有效.显然,这不能满足我的需求,但可以验证构建是否正常工作.

是什么导致了这种非常奇怪的行为?我还可以做些什么来进一步调试此问题?

我try 过的东西

  • 更改 node 版本,范围从14到18.8.0
  • 更改计算机资源大小
  • 更改Docker的选项,包括向构建作业(job)的extra-build-args字段添加--memory标志
  • 移除这yarn.lock
  • 清除 node 缓存
  • 删除node_modules文件夹

相关资源:

这是一条线索:

#16 [11/11] RUN NODE_OPTIONS="--max_old_space_size=8192" yarn build
#16 sha256:da0777711cb35943386ef4812f2df1ff4932fb5bee717be330a217104e5240c7
#16 0.178 
#16 0.178 <--- Last few GCs --->
#16 0.178 
#16 0.178 [1:0x570e320]      100 ms: Mark-sweep 1.2 (3.5) -> 1.2 (3.5) MB, 2.2 / 0.0 ms  (average mu = 0.818, current mu = 0.007) allocation failure scavenge might not succeed
#16 0.178 [1:0x570e320]      102 ms: Mark-sweep (reduce) 1.2 (3.5) -> 1.2 (3.5) MB, 2.3 / 0.0 ms  (average mu = 0.704, current mu = 0.006) last resort GC in old space requested
#16 0.178 [1:0x570e320]      104 ms: Mark-sweep (reduce) 1.2 (2.5) -> 1.1 (3.5) MB, 2.3 / 0.0 ms  (average mu = 0.549, current mu = 0.010) last resort GC in old space requested
#16 0.178 
#16 0.178 
#16 0.178 <--- JS stacktrace --->
#16 0.178 
#16 0.178 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
#16 ERROR: process "/bin/sh -c NODE_OPTIONS=\"--max_old_space_size=8192\" yarn build" did not complete successfully: exit code: 132
------
 > [11/11] RUN NODE_OPTIONS="--max_old_space_size=8192" yarn build:
------
Dockerfile:32
--------------------
  31 |     
  32 | >>> RUN NODE_OPTIONS="--max_old_space_size=8192" yarn build
  34 |     
--------------------
error: failed to solve: rpc error: code = Unknown desc = process "/bin/sh -c NODE_OPTIONS=\"--max_old_space_size=8192\"   CI_BUILD=${CI_BUILD} DEPLOYMENT_VERSION=${DEPLOYMENT_VERSION} yarn build" did not complete successfully: exit code: 132

以下是Dockerfile的相关部分:

FROM node:14.18.0-alpine
WORKDIR /app

RUN apk update
RUN apk add python3
RUN apk add git gnupg jq g++ make py3-pip

COPY package.json yarn.lock ./
RUN yarn
RUN yarn add pm2@5.2.0 --global

COPY . .

RUN NODE_OPTIONS="--max_old_space_size=8192" yarn build

EXPOSE 3001

CMD [ "npx", ... ]

这是来自CircleCI config.yml的工作:

  build_and_push_image:
    machine:
      image: ubuntu-2004:202101-01
    resource_class: arm.xlarge
    steps:
      - checkout
      - docker/pull:
          images: 'node:16.14.2'
      - aws-ecr/build-and-push-image:
          aws-access-key-id: AWS_ACCESS_KEY_ID
          aws-secret-access-key: AWS_SECRET_ACCESS_KEY
          aws-cli-version: latest
          create-repo: true
          skip-when-tags-exist: true  
          dockerfile: Dockerfile
          extra-build-args: >
            --build-arg GPG_ENCRYPT_PASSPHRASE
            --build-arg BUILD_STAGE
            --build-arg CI_BUILD=true
          platform: linux/arm64/v7
          push-image: true
          registry-id: AWS_ACCOUNT_ID
          region: $AWS_REGION
          repo: $PROJECT_NAME
          tag: $version_tag

推荐答案

经过几个小时的反复调试之后,我将以下更改修改为config.yml:

  build_and_push_image:
    machine:
      image: ubuntu-2004:202101-01
    resource_class: arm.xlarge
    steps:
      - checkout
      - docker/pull:
          images: 'node:16.14.2'
      - aws-ecr/build-and-push-image:
          aws-access-key-id: AWS_ACCESS_KEY_ID
          aws-secret-access-key: AWS_SECRET_ACCESS_KEY
          aws-cli-version: latest
          create-repo: true
          skip-when-tags-exist: true  
          dockerfile: Dockerfile
          extra-build-args: >
            --build-arg GPG_ENCRYPT_PASSPHRASE
            --build-arg BUILD_STAGE
            --build-arg CI_BUILD=true

-         platform: linux/arm64/v7
+         platform: linux/arm64

          push-image: true
          registry-id: AWS_ACCOUNT_ID
          region: $AWS_REGION
          repo: $PROJECT_NAME
          tag: $version_tag

我不确定为什么这会奏效,但对于future 被这一功能阻挡的其他人,我有以下最好的 idea :

docker context create builder

# This here is interesting - it is using qemu to emulate for builds 
# See https://github.com/tonistiigi/binfmt

docker run --privileged --rm tonistiigi/binfmt --install all
docker --context builder buildx create --use
docker --context builder buildx build \
  -f "${PARAM_PATH}"/"${PARAM_DOCKERFILE}" \
  ${docker_tag_args} \
  --platform "${PARAM_PLATFORM}" \
  --progress plain \
  "$@" \
  "${PARAM_PATH}"

Node.js相关问答推荐

Mongoose:如何在文档中推送到Caped(有限大小,滚动窗口)数组?

已知NPM无法在node.js V12上运行的问题

如何在Firebase Cloud Function v2计划函数中设置代码中的时区?

带有apache Couch-db和Nano的推荐引擎:过滤特定用户的视图

使用ReadableStream.管道时NodeJS Crypto Hash不正确

如何呈现ejs.renderFile中包含的子模板?

为什么我的 Node.js 应用程序在登录时无法正确验证密码(使用 Passport-local 和 bcryptjs)?

NPM如何管理node_modules传递依赖?

在 .htaccess 中从非 www 切换到 www 后如何解决无法访问该站点?

处理 UTC 日期和future

为什么 $or 在带有正则表达式的mongoose 中不能正常工作

图像存储在后端文件夹中,但使用 multer 和 react.js 在前端找不到

如何让 vscode 假设一个 node.js 上下文,以便它不假设 `fetch` 存在?

如果 express.js (node.js) http 请求在完成之前关闭会发生什么?

突然 React 无法执行create-react-app命令.为什么会发生这种情况,我该如何解决?

如何在 mongoDB 中用值 0 填充缺失的文档?

Node.js 表达的 Error 对象expose 了哪些属性?

node 应用程序是否有任何独立的 gui 模块

使用 node 的内置调试器判断变量?

续集findbyid不是一个函数,但显然findAll是