自定义 Dev Containers 功能

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

在设置开发环境时,我们都经历过这样的时刻——“哦,我只需要一件事!” – 这个“东西”是一种用于您的项目的语言或工具集(或者可能是更多???)。

Dev Containers 是简化环境设置的好方法 - 它们提供了完整的编码环境以及项目所需的工具。它们使用图像、Dockerfile 或 Docker Compose 文件和 进行配置devcontainer.json,这是一种元数据格式,用于通过开发特定的内容和设置来丰富容器。

创建 Dev Containers 时,您可能会有同样的“我只需要一件东西!” 反复反应 – 也许您在 Dockerfile 中使用 Node.js 映像,只需要添加 Git。或者,您可能需要添加更复杂的内容,例如在 Dev Containers 中使用 Docker 或 Kubernetes。 Dev Containers 很棒,因为任何访问您的代码的人都会对您添加的所有工具拥有相同、一致的体验 - 但添加它们的最佳方式是什么?

如果有一种简单的方法可以在您的 Dev Containers 中安装该额外工具,只需提及该工具的名称和版本,会怎么样?或者,如果作为工具用户或作者,您可以创建一种简单的方法供其​​他人安装它怎么办?共享手动脚本有助于重用,但在引用脚本时,您可能会忘记引用容器或工具设置,例如启用对 Go、Rust 或 C++ 调试的 ptrace 支持、添加在容器启动时触发的特定入口点,或者确保包含正确的 VS Code 扩展。

特征

我们很高兴与您分享 Dev Containers 功能,帮助您在 Dev Containers 中顺利获取所需的工具!

功能是安装代码、容器配置和/或设置和扩展的独立单元,旨在在 Dev Containers 中启用新的开发功能。它们可以构建为与各种基础容器镜像一起使用。作为我们开放 Dev Containers 规范工作的一部分,我们对您可以在哪里获取预先创建的功能以及如何创作和分发自己的功能进行了一些改进。

让我们看看有哪些新功能以及如何开始使用任何 Dev Containers 支持工具或服务(例如 VS Code Dev Containers扩展或GitHub Codespaces)的功能!

将功能添加到您的 Dev Containers

Dev Containers 功能提供了一种将 Dev Containers 元数据与某些安装步骤关联的快速方法。您可以通过简单的参考将它们添加到您的 Dev Containers 中。

这些功能现在可以作为OCI 工件存储在任何支持的容器注册表中,这意味着您可以使用与引用容器映像相同类型的标识符来引用它们。我们已将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,公开发布的功能可以通过现有的 Dev Containers 配置体验(例如在 VS Code Dev Containers扩展中提供)来添加。

可用功能的规范站点列表

您甚至可以通过 Dev Containers CLI、GitHub Action 或 Azure DevOps 任务将 Dev Containers 与您最喜爱的 CI 系统中的功能结合使用。我们在devcontainers/ci存储库中提供了 GitHub Action 和 Azure DevOps 任务。 Dev Containers CLI、GitHub Action 或 Azure DevOps 任务也可用于预构建包含功能内容的映像,以加快启动时间。

如果您不仅想使用公开可用的功能,还想创建自己的私人或公共功能来共享,请继续阅读!

创作

开始创建自己的功能的一个好地方是新的功能模板存储库。除了为给定功能的内容提供一个好的模板之外,该模板还包括一个 GitHub Actions 工作流程来快速发布它们,使用您的帐户的GitHub 容器注册表(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将合并到最终 Dev Containers 中的“片段”。例如,如果任何功能"privileged": true在其配置中指示,则整个 Dev Containers 将使用该--privileged标志启动。

功能可以用多种语言编写,最简单的是 shell 脚本。如果某个功能是用不同的语言编写的,则有关它的信息应包含在元数据中,以便用户可以对其做出明智的选择。

注意:虽然 install.sh 将以任何语言运行功能,但如果您使用 Dev Containers 中不存在的解释语言编写功能,则代码将无法执行。请务必在 install.sh 中获取您所需的语言。

您应该确保您公开发布的功能除了该功能之外还检查并安装依赖项。

此外,公共功能很可能在 arm64 或 x86_64 机器上使用 - 因此请务必尽可能适应这一点。

您可以查看规范中的devcontainer-feature.json属性以及devcontainers/features存储库中的公共示例。

现在我们已经了解了如何创建功能,那么如何将其分发给其他人呢?

分配

功能以 tarball 形式分发。tarball 包含 Feature 子目录的全部内容,包括devcontainer-feature.jsoninstall.sh和该目录中的任何其他文件。

开放容器倡议( OCI) 定义了容器和容器资源的行业标准。我们将功能视为 OCI 工件,并使用OCI 注册表的概念来分发功能。

上面提到的功能模板存储库包括一个GitHub Actions 工作流程,用于自动化发布过程。它将功能打包到 tarball 中,并将资产作为 OCI 工件发布到 GHCR。release.yaml通过在 GitHub 上存储库的“操作”选项卡左侧选择模板存储库来触发工作流。GitHub Action 会将功能发布到<owner>/<repo>命名空间下的 GHCR。仅当功能中的版本属性devcontainer-feature.json更新时,才会重新发布功能。

注意: GHCR 的一个手动步骤是将 OCI包标记为“public”。每个功能只需执行一次。私有功能不需要此步骤,只要您使用注册表的凭据登录 Docker CLI,就可以访问私有功能。

与社区分享您的功能

如果您希望您的贡献出现在 VS Code Dev ContainersGitHub Codespaces UI 中以用于创建 Dev Containers ,您可以执行以下步骤:

合并后,您的更改将显示在container.dev/collections中。

功能安装顺序

如果我的功能只能在另一功能之后安装怎么办?作为功​​能作者,您可能会发现您的功能应该在其他功能之前或之后安装。在您的 中devcontainer-feature.json,您可以使用该installsAfter属性列出应在其之前执行的功能。

作为最终用户,您可以overrideFeatureInstallOrder使用devcontainer.json. 此数组中的任何功能 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. overrideFeatureInstallOrder用户的属性devcontainer.json。允许用户控制其功能的执行顺序。
  2. installsAfter定义为功能的一部分的属性devcontainer-feature.json

您可以在规范中阅读有关功能执行和安装顺序的更多信息。

还有什么是新的?

除了新的功能存储库之外,我们最近还开源了一个新的devcontainers/images存储库,我们在其中托管之前位于vscode-dev-containers存储库中的一组特定图像。

我们正在为 Dev Containers 模板(我们在vscode-dev-containers中称为“定义” )制定社区分发计划,我们预计该计划与功能类似。我们一定会在 vscode-dev-containers 存储库中发布更新,就像我们在宣布新功能和图像存储库时所做的那样。

我怎样才能了解更多?

这篇文章只是触及了功能的表面,我们很高兴您能够尝试它们!

正如上述内容中所链接的,了解更多有关功能的内容以及如何分发它们的最佳位置是 Dev Containers 规范的功能功能分发页面。

我们期待您在使用、创建和发布功能时提供反馈 - 我们很想听听它们在功能功能分发问题提案中如何为您工作。

如果您有兴趣参与整个规范或连接另一个工具来利用它,请查看 Dev Containers 规范CLI存储库。

快乐的 Dev Containers 创建,快乐的编码!

布里吉特·墨塔夫,@BrigitMurtaugh