🚀 在 VS Code 中

自訂開發容器功能

2022 年 9 月 15 日,Brigit Murtaugh 撰寫,@BrigitMurtaugh

我們都有過這種經驗,在設定開發環境時,會想:「喔,我只需要再一個東西!」而這個「東西」就是專案需要用到的另一種語言或工具組 (或甚至更多 😊)。

開發容器是簡化環境設定的絕佳方法 - 它們提供完整的程式碼撰寫環境,內含專案所需的工具。它們是使用映像、Dockerfile 或 Docker Compose 檔案以及 devcontainer.json 進行設定,後者是一種中繼資料格式,用於以開發特定內容和設定來豐富容器。

在建立開發容器時,您可能會重複出現相同的「我只需要再一個東西!」反應 – 也許您在 Dockerfile 中使用 Node.js 映像,而只需要新增 Git。或者,您可能需要新增更複雜的東西,例如從開發容器內使用 Docker 或 Kubernetes。開發容器很棒,因為任何存取您程式碼的人都會有相同且一致的體驗,包含您新增的所有工具 – 但新增這些工具的最佳方式是什麼?

如果有一種簡單的方法可以在您的開發容器中安裝額外的工具,只需提及工具的名稱和版本即可,那會怎麼樣?或者,如果您是工具使用者或作者,您可以建立一種簡單的方式讓其他人安裝它,那又會怎麼樣?共用手動指令碼有助於重複使用,但在參考指令碼時,您可能會忘記參考容器或工具設定,例如啟用 ptrace 支援以進行 Go、Rust 或 C++ 偵錯、新增在容器啟動時觸發的特定進入點,或確保包含正確的 VS Code 擴充功能。

功能

我們很高興分享開發容器功能可協助您順利地在開發容器中取得所需的工具!

功能是獨立的安裝程式碼、容器組態,和/或設定與擴充功能單元,旨在在您的開發容器中啟用新的開發功能。它們可以建置為與各種基礎容器映像搭配使用。作為我們在 開放開發容器規格 上工作的一部分,我們已針對您可以在哪裡取得預先建立的功能,以及如何撰寫和發佈您自己的功能進行了一些改進。

讓我們看看有哪些新功能,以及您如何從任何支援開發容器的工具或服務 (例如 VS Code Dev Containers 擴充功能或 GitHub Codespaces) 開始使用功能!

將功能新增至您的開發容器

開發容器功能提供一種快速方式,將開發容器中繼資料與某些安裝步驟建立關聯。您可以透過簡單的參考將它們新增至您的開發容器。

這些功能現在可以儲存為任何支援容器登錄中的 OCI Artifacts,這表示您可以使用與參考容器映像時使用的相同類型識別碼來參考它們。我們已將 vscode-dev-containers 存放庫中的一些早期功能移至新的 devcontainers/features 存放庫,並在此處使用這種新方法發佈它們。

從 devcontainers/features 存放庫參考不同的功能非常簡單,只需將 features 屬性新增至您的 devcontainer.json 即可。每個功能都有一個 README.md,其中顯示如何參考功能以及可用的選項。

以下範例安裝 godocker-in-docker 功能

"name": "my-project-devcontainer",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
    "ghcr.io/devcontainers/features/go:1": {
        "version": "1.18"
    },
    "ghcr.io/devcontainers/features/docker-in-docker:1": {
        "version": "latest",
        "moby": true
    }
}

您也可以在 規格網站 上探索官方和公開貢獻的功能。可以透過編輯 devcontainer.json 來新增任何功能,而公開發佈的功能可以透過現有的開發容器組態體驗來新增 (例如 VS Code Dev Containers 擴充功能中提供的體驗)。

Specification site list of available Features

您甚至可以使用來自您慣用 CI 系統的功能搭配開發容器,方法是使用 開發容器 CLI、GitHub Action 或 Azure DevOps 工作。我們在 devcontainers/ci 存放庫中提供 GitHub Action 和 Azure DevOps 工作。開發容器 CLI、GitHub Action 或 Azure DevOps 工作也可用於預先建置映像,其中包含功能內容,以加快啟動時間。

如果您不僅想要使用公開可用的功能,還想要建立您自己的私人或公開功能來共用,請繼續閱讀!

撰寫

開始建立您自己的功能的絕佳起點是新的 功能範本 存放庫。除了包含給定功能內容的良好範本之外,此範本也包含 GitHub Actions 工作流程,可讓您快速發佈它們,並針對您的帳戶使用 GitHub Container Registry (GHCR),以盡快開始使用。我們稍後將詳細討論發佈。

功能的原始碼有兩個元件:安裝指令碼 (install.sh) 和組態檔 (devcontainer-feature.json)。

+-- feature
|    +-- devcontainer-feature.json
|    +-- install.sh
|    +-- (other files)

install.sh:安裝進入點指令碼 – 它在概念上會新增為映像 Dockerfile 的圖層,並在建置時執行。此進入點指令碼可以安裝語言 (例如 Ruby) 和工具 (GitHub CLI) 等工具。

devcontainer-feature.json:這包含關於功能的中繼資料、一組可以在安裝期間傳遞至功能安裝指令碼的選項,以及將合併到最終開發容器中的 devcontainer.json「片段」。例如,如果任何功能在其組態中指出 "privileged": true,則整個開發容器將會以 --privileged 旗標啟動。

功能可以使用各種語言撰寫,最直接的是 shell 指令碼。如果功能是以不同的語言撰寫,則應將相關資訊包含在中繼資料中,以便使用者可以就此做出明智的選擇。

注意: 雖然 install.sh 會以任何語言執行功能,但如果您以開發容器中不存在的直譯語言撰寫功能,則程式碼將無法執行。請務必取得您需要的語言作為 install.sh 的一部分。

您應確保您公開發佈的功能除了功能之外,還會檢查並安裝相依性。

此外,公開功能很可能從 arm64 或 x86_64 電腦使用 - 因此請務必在可能的情況下進行調整。

您可以在 規格 中檢閱 devcontainer-feature.json 屬性,以及 devcontainers/features 存放庫中的公開範例。

既然我們已經了解如何建立功能,我要如何將其發佈給其他人?

發佈

功能以 tarball 形式發佈。tarball 包含功能子目錄的完整內容,包括 devcontainer-feature.jsoninstall.sh 和目錄中的任何其他檔案。

開放容器倡議 (OCI) 定義容器和容器資源的產業標準。我們將功能視為 OCI Artifacts,並使用 OCI 登錄 的概念來發佈功能。

上述提及的 功能範本 存放庫包含 GitHub Actions 工作流程,可自動化發佈程序。它會將功能封裝到 tarball 中,並將資產發佈為 OCI artifact 到 GHCR。從範本存放庫觸發 release.yaml 工作流程,方法是在 GitHub 上存放庫的 [Actions] 索引標籤左側選取它。GitHub Action 會將功能發佈到 <owner>/<repo> 命名空間下的 GHCR。只有在更新其 devcontainer-feature.json 中的 version 屬性時,才會重新發佈功能。

注意: 使用 GHCR 的一個手動步驟是將 OCI 套件標示為「公開」。每個功能只需執行一次。私人功能不需要此步驟,只要您已使用登錄的認證登入 Docker CLI,即可存取私人功能。

與社群共用您的功能

如果您希望您的貢獻顯示在 VS Code Dev ContainersGitHub Codespaces UI 中以進行開發容器建立,您可以執行下列步驟

合併後,您的變更將會顯示在 containers.dev/collections

功能安裝順序

如果我的功能應該只在另一個功能之後安裝,那會怎麼樣?身為功能作者,您可能會發現您的功能應該在其他功能之前或之後安裝。在您的 devcontainer-feature.json 中,您可以使用 installsAfter 屬性來列出應在其之前執行的功能。

身為終端使用者,您可以透過 devcontainer.json 中的 overrideFeatureInstallOrder 屬性進一步控制執行順序。此陣列中的任何功能 ID 都會在所有其他功能之前安裝,並依提供的順序安裝。例如

"features": {
      "ghcr.io/devcontainers/features/java:1",
      "ghcr.io/devcontainers/features/node:1",
  },
  "overrideFeatureInstallOrder": [
    "ghcr.io/devcontainers/features/node"
  ]

根據預設,功能會安裝在基礎映像之上,順序由實作工具判斷為最佳順序。

如果在功能的 devcontainer-feature.json 或使用者的 devcontainer.json 中提供下列任何屬性,則會遵守這些屬性指示的順序 (優先順序遞減)。

  1. 使用者 devcontainer.json 中的 overrideFeatureInstallOrder 屬性。允許使用者控制其功能的執行順序。
  2. 定義為功能 devcontainer-feature.json 一部分的 installsAfter 屬性。

您可以在 規格 中深入了解功能執行和安裝順序。

還有哪些新功能?

除了新的功能存放庫之外,我們最近也開放原始碼新的 devcontainers/images 存放庫,我們在此處託管一組特定的映像,這些映像先前位於 vscode-dev-containers 存放庫中。

我們正在為開發容器範本 (我們在 vscode-dev-containers 中稱為「定義」) 開發社群發佈計畫,我們預期這會與功能類似。我們一定會在 vscode-dev-containers 存放庫中發佈更新,就像我們在 宣布新的功能和映像存放庫 時所做的那樣。

如何深入了解?

這篇文章僅觸及您可以使用功能執行的操作的表面,而我們很高興您能試用它們!

如上述內容中所連結,深入了解功能內容以及如何發佈功能的最佳位置是開發容器規格的 功能功能發佈 頁面。

我們期待您在使用、建立和發佈功能時提供意見反應 – 我們很樂意在 功能功能發佈 問題提案中聽到它們對您有何作用。

如果您有興趣參與規格的整體或連接另一個工具以利用它,請查看開發容器 specCLI 存放庫。

祝您開發容器建立順利,程式碼撰寫愉快!

Brigit Murtaugh,@BrigitMurtaugh