建置在建置和推送步驟中失敗

建立並執行建置之後,您的建置未順利完成,且您在建置及推送步驟中收到建置失敗的訊息。

建置及推送步驟是 Code Engine 建置的主要步驟。

  • 如果您選擇 Dockerfile 建置策略,則 BuildKit 會分析 Dockerfile,執行在該處說明的步驟來建立容器映像檔,並推送它。

  • 如果您選擇建置套件建置策略,請檢查來源目錄中的檔案,以判斷所要求的建置類型。 比方說,如果來源目錄包含 pom.xml,建置套件會採用 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

建置套件

建置套件

-儲存器登錄密鑰未 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. 建置套件 -未正確指定建置的來源。 此錯誤的一般原因是來源不在 Git 儲存庫的根目錄中,而是在子目錄中。
-不支援建置套件來建置來源。
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 名稱空間存取權及取回映像檔許可權的服務 ID 推送映像檔。 但是,在此情況下需要此許可權。

  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,以指定如何建置容器映像檔。 如果來源儲存庫不包含此類檔案,則您需要提供此檔案,或將建置套件視為建置策略。 如需相關資訊,請參閱 規劃建置

  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 Hub 速率限制所導致問題的解決方案

當您從 Docker Hub 中提取映像以用於 Code Engine 中的應用程式或作業時,請注意免費計劃(未經身份驗證的)使用者的 Docker 速率限制。 如果您收到 429 錯誤,指出您已達到取回速率限制,則可能會遇到取回限制。 如果您收到此錯誤,請嘗試下列其中一個解決方案。

  • 增加速率限制。 必要的話,您可以向 Docker Hub 進行鑑別,或將帳戶升級至 Docker ProTeam 訂閱。

  • 從 Docker Hub 取回建置的映像檔,並將映像檔發佈在不同的登錄中,例如 IBM Cloud® Container Registry。 然後,從新位置取回映像檔。Code Engine 支援參照單一密鑰。 如果 Dockerfile 建置的基本映像檔是從不同於發佈所產生之建置映像檔的登錄中取回,且這兩個登錄都需要鑑別,則您可以使用 kubectl 來建立 Kubernetes 密鑰,其類型為 kubernetes.io/dockerconfigjson,其中包含這兩個登錄的認證。 如需使用這兩個登錄的存取認證的相關資訊,請參閱 從專用儲存庫取回映像檔的Kubernetes 說明文件

建置套件不支援建置來源的解決方案

若要檢查 Code Engine中是否支援建置來源儲存庫,請參閱受支援執行時期的 選擇建置策略。 如果列出您的語言,請檢查鏈結的範例,並確定您已正確建構來源,以便建置套件可以順利偵測及建置它們。 如果您找不到適合您來源的建置套件,或建置套件執行方式的標準化方式不符合您的需求,則您可以指定 Dockerfile,在 Dockerfile 中手動說明容器建置,然後切換至在建置配置中使用 dockerfile 建置策略。

Docker 建置問題的解決方案

如果建置及推送步驟失敗問題不是記憶體、容器登錄密鑰或 Dockerfile 的問題,則可能是 Docker 建置的問題。 問題可能是 Dockerfile 本身的錯誤,例如語法錯誤,或它所執行之作業的正確性。 問題也可能在您的原始碼中,例如,如果包含 Java® 程式碼,則可能無法編譯。

如果您已在本端順利建置專案,但相同的原始碼未建置在 Code Engine中,則您在本端可能會有不在 Git 儲存庫中的可用檔案。 例如,若為 Node.js 專案,一般會在本端執行 npm install 指令,以便將專案相依關係下載並放置在專案目錄內的 node_modules 目錄中。 最好將 node_modules 目錄併入 .gitignore 檔案 中,以保持 Git 儲存庫較小。 常見的錯誤是忘記在 Dockerfile 中同時執行 npm install (或 npm ci)。 如果您將整個專案複製到容器中 (例如,在 Dockerfile 中使用 COPY . /app 指令) ,則您在本端執行的 Docker 建置可以存取本端 node_modules 目錄。 但是,Code Engine 建置會從全新移出的 Git 儲存庫執行,且無法存取 node_modules 目錄。 因此,您必須在 Dockerfile 中執行 npm install (或 npm ci),作為建置的一部分。

較好的作法是將 node_modules 之類的目錄也包含在 .dockerignore 檔案 中,以便您在本端執行的 Docker 建置行為與 Code Engine 建置相同。

在本端順利建置專案,但因 Code Engine 建置而失敗的另一個原因是安全限制。 與應用程式及批次工作一樣,Code Engine 不容許在 Code Engine 叢集內進行任意系統作業。 這些大部分系統作業都與 Docker 建置無關。 不過,Code Engine 不容許開啟特許埠的伺服器 Socket。 範圍為 0 to 1023。 例如,如果您建置 Web 應用程式,且您的建置包含啟動 Web 應用程式伺服器的測試步驟,則您必須使用此伺服器具有較高數目的埠。