🚀 在 VS Code 中

自訂開發容器功能

2022 年 9 月 15 日,作者:Brigit Murtaugh,@BrigitMurtaugh

我們都曾有過設定開發環境時的經驗——「喔,我只需要再一個東西!」——這個「東西」就是為了處理您的專案所需的一種或多種語言或工具組(或更多 😊)。

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

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

如果有一種簡單的方法可以在您的開發容器中安裝額外的工具,只需提及工具的名稱和版本即可,那會怎麼樣?或者,如果身為工具使用者或作者,您可以建立一種簡單的方法供其他人安裝它,那又會怎麼樣?共用手動指令碼可以幫助重複使用,但在參考指令碼時,您可能會忘記參考容器或工具設定,例如為 Go、Rust 或 C++ 偵錯啟用 ptrace 支援、新增在容器啟動時觸發的特定進入點,或確保包含正確的 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 系統的開發容器與功能,方法是使用 dev container CLI、GitHub Action 或 Azure DevOps 工作。我們在 devcontainers/ci 儲存庫中提供了 GitHub Action 和 Azure DevOps 工作。dev container CLI、GitHub Action 或 Azure DevOps 工作也可以用於預先建置映像,其中包含功能內容,以加快啟動時間。

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

撰寫

開始建立您自己的功能的絕佳起點是新的 Features 範本 儲存庫。除了包含給定功能內容的良好範本外,該範本還包括 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 和目錄中的任何其他檔案。

Open Container Initiative (OCI) 定義了容器和容器資源的產業標準。我們將功能視為 OCI Artifacts,並使用 OCI Registry 的概念來發佈功能。

上面提到的 Features 範本 儲存庫包含 GitHub Actions 工作流程,用於自動化發佈程序。它將功能封裝到 tarball 中,並將資產作為 OCI artifact 發佈到 GHCR。從範本儲存庫中選取 Actions 索引標籤左側的 release.yaml 工作流程來觸發它。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