构建和推送步骤中的构建失败
创建并运行构建后,构建未成功完成,并且您在构建和推送步骤中接收到构建失败的消息。
构建和推送步骤是 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
|
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,构建包 |
|
试试这些解决方案之一。
无论您是在控制台还是 CLI 中运行构建,请使用 CLI 对构建问题进行故障诊断。
- 运行
ibmcloud ce buildrun get --name BUILDRUN_NAME
命令以显示构建运行的详细信息。 - 查看命令输出中的
Reason
。
在检查日志并确定潜在的根本原因之后,请使用以下解决操作来帮助您解决问题。
构建期间内存限制的解析
请参阅 超出内存限制时构建失败 以获取解析信息。
构建期间容器注册表问题的解决方案
在此场景中,用于访问容器注册表的注册表私钥不存在,或者该私钥不正确。
-
确定使用的密钥。 使用
ibmcloud ce build get
命令来显示所使用的注册表密钥。 -
确定
.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>
-
如果存在
.dockerconfigjson
密钥,请使用以下命令对该密钥进行解码,该密钥是 base64 编码的字符串。echo "<BASE64_STRING>" | base64 -d {"auths":{"<REGISTRY>":{"username":"<USERNAME>","password":"<PASSWORD>","auth":"<AUTH>"}}}
此命令的输出通常包含一个
<REGISTRY>
键。 -
确认有关密钥的以下信息:
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 名称空间以及有权拉取映像的服务标识推送映像。 但是,这种许可是在这种情况下需要的。
-
-
确定所需的更改后,创建使用更正值的容器注册表私钥。 使用
ibmcloud ce secret create --format
命令; 例如,ibmcloud ce secret create --format registry --name <REGISTRY_SECRET> --server <REGISTRY_SERVER> --username <USERNAME> --password <PASSWORD>
-
更新构建以引用注册表私钥的名称。
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 视为构建策略。 有关更多信息,请参阅 规划构建。
-
如果 Dockerfile 存在,但名称不同或不在根目录中,那么需要在构建中指定其他设置。
- 如果 Dockerfile 不在源存储库的根目录中,那么必须指定
--context-dir
参数并提供包含 Dockerfile 的目录的路径。 - 如果 Dockerfile 的名称不是
Dockerfile
,那么必须指定--dockerfile
参数并提供 Dockerfile 的名称。
- 如果 Dockerfile 不在源存储库的根目录中,那么必须指定
-
根据需要更新构建以使用
--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。
-
请执行下列其中一项操作:
- 从 IBM Cloud Container Registry 名称空间中删除未使用的映像以增加可用空间。
- 从免费套餐升级到标准套餐。
- 增加 IBM Cloud Container Registry 名称空间的配额。
错误信息中包含图像 URL,以帮助您识别受影响的IBM Cloud Container Registry命名空间。 命名空间可以位于IBM Cloud Code Engine项目不同的IBM Cloud账户中。
-
完成更正操作后,请使用
ibmcloud ce buildrun submit
命令来提交新的构建运行。 对于buildrun submit
命令,必须指定--build
选项以提供构建配置的名称。 您可以选择指定--name
选项以提供此构建运行的名称。 如果指定--name
选项,请确保使用与失败的构建运行不同的构建运行名称,或者确保使用ibmcloud ce buildrun delete
命令删除失败的构建运行。 例如ibmcloud ce buildrun submit --build <BUILD_NAME> --name <BUILDRUN_NAME>
未正确指定构建源的解析
发生此错误的典型原因是构建源未位于 Git 存储库的根目录中,而是位于子目录中。 如果构建源不在根目录中,请指定构建中的位置。
-
使用
ibmcloud ce build update
命令更新构建配置,以使用--context-dir
选项来指定 Git 存储库中源的路径; 例如,ibmcloud ce build update --name <BUILD_NAME> --context-dir <CONTEXT_DIR>
-
使用
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
Pro
或Team
预订。 -
从 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 应用程序服务器的测试步骤,那么必须将具有较高数字的端口用于此服务器。