在 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 开发容器扩展或 GitHub Codespaces)开始使用特性!

为您的开发容器添加特性

开发容器特性提供了一种快速方式将开发容器元数据与某些安装步骤关联起来。您可以通过简单的引用将它们添加到开发容器中。

这些特性现在可以作为 OCI 工件存储在任何受支持的容器注册表中,这意味着您可以使用引用容器镜像的相同类型的标识符来引用它们。我们将一些早期位于 vscode-dev-containers 仓库中的特性移到了新的 devcontainers/features 仓库中,并使用这种新方法发布它们。

从 devcontainers/features 仓库引用不同的特性就像向 devcontainer.json 添加 features 属性一样简单。每个特性都有一个 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 开发容器扩展中可用的体验)来添加公开发布的特性。

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 容器注册表 (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 工件,并使用OCI 注册表的概念来分发特性。

上面提到的特性模板仓库包含一个GitHub Actions 工作流来自动化发布过程。它将特性打包成 tarball 并将资产作为 OCI 工件发布到 GHCR。通过在 GitHub 仓库的 Actions 标签左侧选择 release.yaml 工作流来触发它。GitHub Action 会将特性发布到 GHCR 中,命名空间为 <owner>/<repo>。特性仅在其 devcontainer-feature.json 中的 version 属性更新时才会重新发布。

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

与社区共享您的特性

如果您希望您的贡献出现在 VS Code 开发容器GitHub Codespaces 用于创建开发容器的用户界面中,您可以执行以下步骤

合并后,您的更改将显示在 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.json 中提供了以下任何属性,则会遵循这些属性指示的顺序(优先级递减)。

  1. 用户 devcontainer.json 中的 overrideFeatureInstallOrder 属性。允许用户控制其特性的执行顺序。
  2. 作为特性 devcontainer-feature.json 的一部分定义的 installsAfter 属性。

您可以在规范中阅读更多关于特性执行和安装顺序的信息。

还有什么新内容?

除了新的特性仓库,我们最近还开源了一个新的 devcontainers/images 仓库,用于托管之前位于 vscode-dev-containers 仓库中的特定镜像集。

我们正在制定开发容器模板(在 vscode-dev-containers 中我们将其称为“定义”)的社区分发计划,我们预计这与特性类似。我们将在 vscode-dev-containers 仓库中发布更新,就像我们宣布新的特性和镜像仓库时所做的那样。

如何了解更多信息?

这篇博文只是初步介绍了特性所能实现的功能,我们很高兴您能尝试它们!

正如上面内容中链接所示,了解特性组成以及如何分发的最佳位置是开发容器规范的特性特性分发页面。

我们期待您在使用、创建和发布特性时的反馈——我们很高兴在特性特性分发议题提案中听到它们对您的作用。

如果您有兴趣参与整个规范或将其他工具连接以利用它,请查看开发容器规范CLI仓库。

祝您愉快地创建开发容器,愉快地编码!

Brigit Murtaugh, @BrigitMurtaugh