IBM Cloud Docs
构建和推送步骤中的构建失败

构建和推送步骤中的构建失败

创建并运行构建后,构建未成功完成,并且您在构建和推送步骤中接收到构建失败的消息。

构建和推送步骤是 Code Engine 构建的主要步骤。

  • 如果选择了 Dockerfile 构建策略,那么 BuildKit 会分析 Dockerfile,执行其中描述的步骤以创建容器映像并推送该映像。

  • 如果选择了 Buildpack 构建策略,请检查源目录中的文件以确定请求的构建类型。 例如,如果源目录包含 pom.xml,那么 Buildpack 将采用 Maven 类型并运行 mvn -Dmaven.test.skip=true 包构建。 如果它找到 package.json 文件,那么假定构建适用于 Node.js 应用程序并运行 npm install。 结果将与所需的运行时环境一起打包到映像中,并推送到容器注册表。

    示例错误消息

    Summary: Failed to execute build run
    Reason:  "step-build-and-push" exited with code 1 (image: "icr.io/obs/codeengine/buildkit/builder:v0.9.0-rc.19@sha256:a11e2348f9ee40822fc28dcb501c57cd02ebd31fb441841bfe5c144cc9d77fc6"); for logs run: kubectl -n <PROJECT_NAMESPACE> logs <BUILDRUN_NAME>-865rg-pod-m5lrs -c step-build-and-push
    

    要确定根本原因,请检查步骤的日志。 运行 ibmcloud ce buildrun logs 命令。 关注失败步骤的日志,

    ibmcloud ce buildrun logs -n <BUILDRUN_NAME>
    

下表描述了此场景的错误文本和潜在根本原因。

构建和推送步骤的错误文本和基本案例
错误消息包含 策略 潜在的根本原因
Killed Dockerfile,构建包 -已达到内存限制。
error checking pushed permissions

ERROR: failed to export: failed to write image to the following tags: [...] UNAUTHORIZED

ERROR: failed to export: failed to write image to the following tags: [...] unsupported status code 401

Dockerfile

buildpack

buildpack

-未定义容器注册表私钥 defined.
-容器注册表私钥不是正确的 type.
-容器注册表私钥不适用于正确的容器 registry.
-容器注册表私钥不允许推送到容器注册表。
error: failed to solve: failed to read dockerfile: open /tmp/buildkit-mount306846082/Dockerfile: no such file or directory Dockerfile -Dockerfile 不在源存储库的根目录中。
-源存储库根本不包含 Dockerfile。
error: failed to solve: unexpected status: 403 Forbidden
DENIED: You have exceeded your storage quota. Delete one or more images, or review your storage quota and pricing plan. For more information, see https://ibm.biz/BdjFwL
Dockerfile,构建包 -使用 IBM Cloud® Container Registry 并达到配额限制。
ERROR: No buildpack groups passed detection. buildpack -未正确指定构建的源。 此错误的典型原因是源不在 Git 存储库的根目录中,而是在子目录中。
-不支持 Buildpack 来构建源。
429 Too Many Requests - Server message: toomanyrequests: You have reached your pull rate limit. Dockerfile -已达到 Dockerfile 拉取速率限制。
任何其他错误消息 Dockerfile,构建包
  • Docker 构建存在问题。
    -源代码存在问题。

试试这些解决方案之一。

无论您是在控制台还是 CLI 中运行构建,请使用 CLI 对构建问题进行故障诊断。

  1. 运行 ibmcloud ce buildrun get --name BUILDRUN_NAME 命令以显示构建运行的详细信息。
  2. 查看命令输出中的 Reason

在检查日志并确定潜在的根本原因之后,请使用以下解决操作来帮助您解决问题。

构建期间内存限制的解析

请参阅 超出内存限制时构建失败 以获取解析信息。

构建期间容器注册表问题的解决方案

在此场景中,用于访问容器注册表的注册表私钥不存在,或者该私钥不正确。

  1. 确定使用的密钥。 使用 ibmcloud ce build get 命令来显示所使用的注册表密钥。

  2. 确定 .dockerconfigjson 密钥是否存在。 对注册表私钥使用 ibmcloud ce secret get 命令。 请注意,私钥数据是使用 base64 编码的,不会直接显示; 但是,私钥包含凭证。 在命令输出中,检查 Data 部分。 它必须包含名为 .dockerconfigjson 的密钥。 如果未显示 .dockerconfigjson 密钥,那么此私钥不适合向容器注册表进行认证,您需要创建正确的私钥并在构建中对其进行引用。 有关更多信息,请参阅 添加对专用容器注册表的访问权

    示例输出

    $ ibmcloud code-engine secret get -n <REGISTRY_SECRET>
    Getting secret <REGISTRY_SECRET>...
    OK
    
    Name:        <REGISTRY_SECRET>
    ID:          <REGISTRY_SECRET_ID>
    Project:     <PROJECT_NAME>
    Project ID:  <PROJECT_NAMESPACE>
    Age:         8s
    Created:     2021-02-12T10:26:59-06:00
    
    Data:
    ---
    .dockerconfigjson: <BASE64_STRING>
    
  3. 如果存在 .dockerconfigjson 密钥,请使用以下命令对该密钥进行解码,该密钥是 base64 编码的字符串。

    echo "<BASE64_STRING>" | base64 -d
    {"auths":{"<REGISTRY>":{"username":"<USERNAME>","password":"<PASSWORD>","auth":"<AUTH>"}}}
    

    此命令的输出通常包含一个 <REGISTRY> 键。

  4. 确认有关密钥的以下信息:

    a. 查看 <REGISTRY> 值。 此值必须与构建的映像相匹配。

    • 如果映像名称位于 IBM Cloud Container Registry上,例如 us.icr.io/aNamespace/anImage,那么 <REGISTRY> 需要为 us.icr.io

    • 如果映像名称是没有任何主机名的 docker.io/aNamespace/aRepository/aNamespace/aRepository,那么构建将使用 Docker Hub。 在这种情况下,<REGISTRY> 必须为 https://index.docker.io/v1/

    b. 查看 <USERNAME> 值。 如果注册表是 IBM Cloud Container Registry,那么必须使用 API 密钥进行认证。 <USERNAME> 需要为 iamapikey,而密码需要为 API 密钥。 有关创建 API 密钥的步骤,请参阅 自动访问 IBM Cloud Container Registry

    c. 需要验证凭证。IBM Cloud® Identity and Access Management (IAM) 允许以细颗粒度方式分配许可权。 例如,可能不允许有权访问 IBM Cloud Container Registry 名称空间以及有权拉取映像的服务标识推送映像。 但是,这种许可是在这种情况下需要的。

  5. 确定所需的更改后,创建使用更正值的容器注册表私钥。 使用 ibmcloud ce secret create --format 命令; 例如,

    ibmcloud ce secret create --format registry --name <REGISTRY_SECRET> --server <REGISTRY_SERVER> --username <USERNAME> --password <PASSWORD>
    
  6. 更新构建以引用注册表私钥的名称。

    a. 使用 ibmcloud ce build update 命令更新构建配置以使用注册表私钥的名称; 例如,

    ibmcloud ce build update --name <BUILD_NAME> --registry-secret <REGISTRY_SECRET>
    

    b. 使用 ibmcloud ce buildrun submit 命令来提交新的构建运行。 对于 buildrun submit 命令,必须指定 --build 选项以提供构建配置的名称。 您可以选择指定 --name 选项以提供此构建运行的名称。 如果指定 --name 选项,请确保使用与失败的构建运行不同的构建运行名称,或者确保使用 ibmcloud ce buildrun delete 命令删除失败的构建运行。 例如

    ibmcloud ce buildrun submit --build <BUILD_NAME> --name <BUILDRUN_NAME>
    

构建期间找不到 Dockerfile 的解析

Docker 构建需要一个 Dockerfile,用于指定如何构建容器映像。 如果源存储库不包含此类文件,那么您需要提供此文件或将 buildpack 视为构建策略。 有关更多信息,请参阅 规划构建

  1. 如果 Dockerfile 存在,但名称不同或不在根目录中,那么需要在构建中指定其他设置。

    • 如果 Dockerfile 不在源存储库的根目录中,那么必须指定 --context-dir 参数并提供包含 Dockerfile 的目录的路径。
    • 如果 Dockerfile 的名称不是 Dockerfile,那么必须指定 --dockerfile 参数并提供 Dockerfile 的名称。
  2. 根据需要更新构建以使用 --context-dir--dockerfile 选项。

    a. 使用 ibmcloud ce build update 命令更新构建配置以根据需要使用 --context-dir--dockerfile 选项; 例如,

    ibmcloud ce build update --name <BUILD_NAME> [--context-dir <CONTEXT_DIR>] [--dockerfile <DOCKERFILE_NAME>]
    

    b. 使用 ibmcloud ce buildrun submit 命令来提交新的构建运行。 对于 buildrun submit 命令,必须指定 --build 选项以提供构建配置的名称。 您可以选择指定 --name 选项以提供此构建运行的名称。 如果指定 --name 选项,请确保使用与失败的构建运行不同的构建运行名称,或者确保使用 ibmcloud ce buildrun delete 命令删除失败的构建运行。 例如

    ibmcloud ce buildrun submit --build <BUILD_NAME> --name <BUILDRUN_NAME>
    

构建期间达到 IBM Cloud Container Registry 配额限制

IBM Cloud Container Registry 具有两个服务套餐,一个免费套餐和一个标准套餐。 对于免费套餐,IBM Cloud Container Registry 会应用严格限制,尤其是对可存储的图像大小 (总计 500 MB)。 对于标准套餐,您可以配置配额。 有关更多信息,请参阅 关于 IBM Cloud Container Registry

  1. 请执行下列其中一项操作:

    • 从 IBM Cloud Container Registry 名称空间中删除未使用的映像以增加可用空间。
    • 从免费套餐升级到标准套餐。
    • 增加 IBM Cloud Container Registry 名称空间的配额。

    错误信息中包含图像 URL,以帮助您识别受影响的IBM Cloud Container Registry命名空间。 命名空间可以位于IBM Cloud Code Engine项目不同的IBM Cloud账户中。

  2. 完成更正操作后,请使用 ibmcloud ce buildrun submit 命令来提交新的构建运行。 对于 buildrun submit 命令,必须指定 --build 选项以提供构建配置的名称。 您可以选择指定 --name 选项以提供此构建运行的名称。 如果指定 --name 选项,请确保使用与失败的构建运行不同的构建运行名称,或者确保使用 ibmcloud ce buildrun delete 命令删除失败的构建运行。 例如

    ibmcloud ce buildrun submit --build <BUILD_NAME> --name <BUILDRUN_NAME>
    

未正确指定构建源的解析

发生此错误的典型原因是构建源未位于 Git 存储库的根目录中,而是位于子目录中。 如果构建源不在根目录中,请指定构建中的位置。

  1. 使用 ibmcloud ce build update 命令更新构建配置,以使用 --context-dir 选项来指定 Git 存储库中源的路径; 例如,

    ibmcloud ce build update --name <BUILD_NAME> --context-dir <CONTEXT_DIR>
    
  2. 使用 ibmcloud ce buildrun submit 命令来提交新的构建运行。 对于 buildrun submit 命令,必须指定 --build 选项以提供构建配置的名称。 您可以选择指定 --name 选项以提供此构建运行的名称。 如果指定 --name 选项,请确保使用与失败的构建运行不同的构建运行名称,或者确保使用 ibmcloud ce buildrun delete 命令删除失败的构建运行。 例如

    ibmcloud ce buildrun submit --build <BUILD_NAME> --name <BUILDRUN_NAME>
    

由于 Docker 中心速率限制而导致的问题的解决方案

从 Docker Hub 拉取映像以用于 Code Engine中的应用程序或作业时,请注意免费套餐 (匿名) 用户的 Docker 速率限制。 如果您收到 429 错误,指示您已达到拉取速率限制,那么可能会迂到拉取限制。 如果收到此错误,请尝试下列其中一个解决方案。

  • 增加速率限制。 您可以向 Docker Hub 认证,或者根据需要将帐户升级到 Docker ProTeam 预订。

  • 从 Docker Hub 中拉取已构建的映像,并在其他注册表 (例如 IBM Cloud® Container Registry) 中发布该映像。 然后,从新位置提取图像。Code Engine 支持引用单个私钥。 如果 Dockerfile 构建的基本映像是从与发布所生成的已构建映像的注册表不同的注册表中提取的,并且这两个注册表都需要认证,那么您可以使用 kubectl 来创建类型为 kubernetes.io/dockerconfigjson 的 Kubernetes 私钥,其中包含这两个注册表的凭证。 有关使用两个注册表的访问凭证的信息,请参阅 Kubernetes 文档中有关从专用存储库中拉取映像的信息

buildpack 不支持的构建源的解析

要检查 Code Engine中是否支持构建源存储库,请参阅 选择构建策略 以了解受支持的运行时。 如果列出了您的语言,请检查链接的样本并确保正确构造源,以便 buildpack 可以成功检测和构建这些样本。 如果找不到适合源的 buildpack,或者 buildpack 运行构建的标准化方法无法满足您的需求,那么可以指定 Dockerfile,在 Dockerfile 中手动描述容器构建,然后切换为在构建配置中使用 dockerfile 构建策略。

解决 Docker 构建的问题

如果构建和推送步骤失败问题不是内存问题,容器注册表私钥问题或 Dockerfile 问题,那么 Docker 构建很可能存在问题。 问题可能是 Dockerfile 本身的错误 (例如,语法错误) 或它执行的操作的正确性。 此问题也可能存在于源代码中,例如,如果包含 Java® 代码,那么此问题可能无法编译。

如果在本地成功构建项目,但同一源代码未在 Code Engine中构建,那么您可能在本地具有不在 Git 存储库中的可用文件。 例如,对于 Node.js 项目,通常在本地运行 npm install 命令,以便下载项目依赖关系并将其放置在项目目录内的 node_modules 目录中。 最好在 .gitignore 文件 中包含 node_modules 目录,以保持 Git 存储库较小。 常见错误是忘记还在 Dockerfile 中运行 npm install (或 npm ci)。 如果将整个项目复制到容器中 (例如,使用 Dockerfile 中的 COPY . /app 命令) ,那么本地运行的 Docker 构建可以访问本地 node_modules 目录。 但是,Code Engine 构建从新检出的 Git 存储库运行,并且无法访问 node_modules 目录。 因此,必须在构建过程中在 Dockerfile 中运行 npm install (或 npm ci)。

最佳做法是在 .dockerignore 文件 中也包含 node_modules 之类的目录,以便您在本地运行的 Docker 构建的行为与 Code Engine 构建的行为相同。

在本地成功构建项目但由于 Code Engine 构建而失败的另一个原因是安全性限制。 与应用程序和批处理作业一样,Code Engine 不允许在 Code Engine 集群中执行任意系统操作。 这些系统操作中的大多数都与 Docker 构建无关。 但是,Code Engine 不允许为特权端口打开服务器套接字。 范围为 0 to 1023。 例如,如果您构建 Web 应用程序,并且您的构建包含用于启动 Web 应用程序服务器的测试步骤,那么必须将具有较高数字的端口用于此服务器。