现已发布!阅读 10 月份的新功能和修复。

创建开发容器

Visual Studio Code 开发容器扩展允许您使用 Docker 容器 作为功能齐全的开发环境。它允许您在容器中打开任何文件夹或存储库,并利用 Visual Studio Code 的全部功能集。您项目中的 devcontainer.json 文件告诉 VS Code 如何访问(或创建)具有定义明确的工具和运行时堆栈的**开发容器**。此容器可用于运行应用程序,或提供代码库所需的其他工具、库或运行时。

创建开发容器的路径

在本文档中,我们将介绍在 VS Code 中创建开发(dev)容器的步骤

  1. 创建一个 devcontainer.json,它描述 VS Code 如何启动容器以及在连接后该做什么。
  2. 使用 Dockerfile 对开发容器进行修改并持久保存更改,例如安装新软件。
  3. 通过 Docker Compose 配置多个容器。
  4. 在进行任何更改后,请构建您的开发容器以确保更改生效。

在完成上述任何步骤后,您将拥有一个功能齐全的开发容器,您可以继续执行本教程的下一步骤以添加更多功能,或停止并开始在您当前拥有的开发环境中工作。

注意:开发容器扩展有一个名为**开发容器:添加开发容器配置文件...**的命令,它允许您从列表中选择预定义的容器配置。如果您希望立即拥有一个完整的开发容器,而不是逐步构建 devcontainer.json 和 Dockerfile,您可以跳过步骤,直接进入 自动创建开发容器

创建 devcontainer.json 文件

VS Code 的容器配置存储在 devcontainer.json 文件中。此文件类似于调试配置的 launch.json 文件,但用于启动(或连接到)您的开发容器。开发容器配置位于 .devcontainer/devcontainer.json 下,或存储为您的项目根目录中的 .devcontainer.json 文件(注意前缀点)。

您可以使用镜像作为您的 devcontainer.json 的起点。镜像就像一个迷你磁盘驱动器,预装了各种工具和操作系统。您可以从容器注册表中拉取镜像,容器注册表是存储镜像的存储库集合。以下是一个简单的 devcontainer.json 示例,它使用预构建的 TypeScript 和 Node.js VS Code 开发容器 镜像

{
  "image": "mcr.microsoft.com/devcontainers/typescript-node:0-18"
}

您可以更改配置以执行以下操作

对于此示例,如果您想将 Code Spell Checker 扩展 安装到您的容器并自动转发端口 3000,您的 devcontainer.json 将如下所示

{
  "image": "mcr.microsoft.com/devcontainers/typescript-node",

  "customizations": {
    "vscode": {
      "extensions": ["streetsidesoftware.code-spell-checker"]
    }
  },
  "forwardPorts": [3000]
}

注意:根据基本镜像中的内容,容器中将已添加其他配置。例如,我们在上面添加了 streetsidesoftware.code-spell-checker 扩展,容器也将包含 "dbaeumer.vscode-eslint",因为 它是 mcr.microsoft.com/devcontainers/typescript-node 的一部分。当使用 devcontainer.json 预构建时,这将自动发生,您可以在 预构建部分 中了解有关预构建的更多信息。

使用上述 devcontainer.json,您的开发容器已具备功能,您可以连接到它并开始在其中进行开发。请尝试使用**开发容器:在容器中重新打开**命令

Quick pick with list of Dev Containers commands

运行此命令后,VS Code 重新启动时,您现在将在 Node.js 和 TypeScript 开发容器中,端口 3000 已转发,ESLint 扩展已安装。连接后,请注意状态栏左侧的绿色远程指示器,它表明您已连接到开发容器

VS Code instance connected to dev container

其他开发容器场景

通过 devcontainer.json 文件,您可以

如果 devcontainer.json 的支持的工作流程无法满足您的需求,您也可以 连接到已运行的容器

提示:想要使用远程 Docker 主机?请参阅 在远程 Docker 主机上开发 文章,了解有关设置的详细信息。

安装其他软件

您可能希望在开发容器中安装其他软件。VS Code 连接到容器后,您可以打开 VS Code 终端并对容器内的操作系统执行任何命令。这使您可以安装新的命令行实用程序,并从 Linux 容器内部启动数据库或应用程序服务。

大多数容器镜像都是基于 Debian 或 Ubuntu,使用 `apt` 或 `apt-get` 命令安装新软件包。 您可以在 Ubuntu 文档 中了解更多关于此命令的信息。 Alpine 镜像包含一个 类似的 `apk` 命令,而 CentOS / RHEL / Oracle SE / Fedora 镜像 使用 `yum`更近期的 `dnf`

您要安装的软件的文档通常会提供具体的说明,但如果您在容器中以 root 身份运行,您可能不需要在命令前加上 `sudo`。

例如

# If running as root
apt-get update
apt-get install <package>

如果您以 root 身份运行,只要您的容器中配置了 `sudo`,您就可以安装软件。 所有预定义的容器都设置了 `sudo`,但是 在容器中添加非 root 用户 文章可以帮助您为自己的容器设置此项。 无论如何,如果您安装和配置了 `sudo`,您将能够在以任何用户(包括 root)身份运行时使用它。

# If sudo is installed and configured
sudo apt-get update
sudo apt-get install <package>

假设您要安装 Git。 您可以在 VS Code 的集成终端中运行以下命令

# If sudo is installed and configured
sudo apt-get update
# Install Git
sudo apt-get install git

您也可以在 `devcontainer.json` 中使用 `“features”` 属性来安装来自预定义的 功能 集或您自己的功能的工具和语言。

例如,您可以使用以下命令安装最新版本的 Azure CLI

"features": {
    "ghcr.io/devcontainers/features/azure-cli:1": {
        "version": "latest"
    }
  }

有关更多详细信息,请参阅 Dev Container 功能规范

重建

当您编辑 `.devcontainer` 文件夹的内容时,您需要重建才能使更改生效。 使用“Dev Containers: Rebuild Container”命令重建您的容器以更新。

但是,如果您 **重建** 容器,您将不得不 **重新安装** 您手动安装的任何内容。 为了避免这个问题,您可以在 `devcontainer.json` 中使用 `postCreateCommand` 属性或自定义 `Dockerfile`。

自定义 `Dockerfile` 将从 Docker 的构建缓存中获益,并且比 `postCreateCommand` 产生更快的重建。 但是,`Dockerfile` 在创建开发容器之前运行,并且工作区文件夹已挂载,因此无法访问工作区文件夹中的文件。 `Dockerfile` 最适合安装与工作区文件无关的软件包和工具。

`postCreateCommand` 操作在创建容器后运行,因此您也可以使用该属性来运行诸如 `npm install` 之类的命令,或在您的源代码树中执行 shell 脚本(如果您已挂载它)。

"postCreateCommand": "bash scripts/install-dependencies.sh"

您也可以使用交互式 bash shell,以便您的 `.bashrc` 被选中,自动为您的环境定制您的 shell

"postCreateCommand": "bash -i scripts/install-dependencies.sh"

像 NVM 这样的工具在不使用 `-i` 将 shell 置于交互模式的情况下将无法正常工作

"postCreateCommand": "bash -i -c 'nvm install --lts'"

该命令需要退出,否则容器将无法启动。 例如,如果您在 `postCreateCommand` 中添加应用程序启动,则该命令将不会退出。

还有一个 `postStartCommand`,它在每次容器启动时都会执行。 参数的行为与 `postCreateCommand` 完全相同,但命令在启动时执行而不是创建时执行。

与其直接在 `devcontainer.json` 中引用镜像或通过 `postCreateCommand` 或 `postStartCommand` 安装软件,不如使用 Dockerfile,这是一种更高效的做法。

Dockerfile

Dockerfile 也将位于 `.devcontainer` 文件夹中。 您可以将 `devcontainer.json` 中的 `image` 属性替换为 `dockerfile`

{
  "build": { "dockerfile": "Dockerfile" },

  "customizations": {
    "vscode": {
      "extensions": ["dbaeumer.vscode-eslint"]
    }
  },

  "forwardPorts": [3000]
}

当您进行诸如安装新软件之类的更改时,即使在重建开发容器后,在 Dockerfile 中进行的更改也会保留。

在您的 Dockerfile 中,使用 `FROM` 指定镜像,使用 `RUN` 指令安装任何软件。 您可以使用 `&&` 将多个命令串联在一起。

FROM mcr.microsoft.com/devcontainers/javascript-node:0-18
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
    && apt-get -y install git

注意:`DEBIAN_FRONTEND` 导出在您继续使用容器时会避免警告。

自动化开发容器创建

与其手动创建 `.devcontainer`,不如从命令面板 (F1) 中选择“Dev Containers: Add Dev Container Configuration Files...”命令,这会将必要的项目文件添加到您的项目作为起点,您可以根据您的需求进一步定制它们。

该命令允许您从一个列表中选择一个预定义的容器配置,该列表基于您文件夹的内容

Add a dev container config

您可以选择的预定义容器配置来自我们的 第一方和社区索引,它是 Dev Container 规范 的一部分。 我们在 devcontainers/templates 存储库 中托管了一组作为规范一部分的模板。 您可以浏览该存储库的 `src` 文件夹以查看每个模板的内容。

在使用“Dev Containers: Add Dev Container Configuration Files...”结束时,您将看到可用功能的列表,这些功能是可以轻松添加到开发容器中的工具和语言。 “Dev Containers: Configure Container Features”允许您更新现有的配置。

Dev container features in Command Palette

您也可以重用现有的 Dockerfile

Select Dockerfile

现在您有了 `devcontainer.json` 和 Dockerfile,让我们看看编辑容器配置文件的一般过程。

完整配置编辑循环

编辑您的容器配置非常容易。 由于重建容器会将容器“重置”为其初始内容(除了您本地源代码),因此如果您编辑容器配置文件(`devcontainer.json`、`Dockerfile` 和 `docker-compose.yml`),VS Code 不会自动重建。 相反,有一些命令可以用于使编辑您的配置变得更容易。

以下是使用这些命令的典型编辑循环

Container edit loop illustration

  1. 从命令面板 (F1) 中的“Dev Containers: Add Dev Container Configuration Files...”开始。
  2. 根据需要编辑 `.devcontainer` 文件夹的内容。
  3. 使用“Dev Containers: Reopen in Container”试一下。
  4. 如果您看到错误,请在出现的对话框中选择“Open Folder Locally”。
  5. 窗口重新加载后,**构建日志** 的副本将出现在控制台中,以便您可以调查问题。 根据需要编辑 `.devcontainer` 文件夹的内容。 (如果您关闭它,您也可以使用“Dev Containers: Show Container Log”命令再次查看日志。)
  6. 运行“Dev Containers: Rebuild and Reopen in Container”,如果需要,跳到步骤 4。

如果您已经有了成功的构建,您仍然可以在连接到容器时根据需要编辑 `.devcontainer` 文件夹的内容,然后在命令面板 (F1) 中选择“Dev Containers: Rebuild Container”,以便更改生效。

您也可以在使用“Dev Containers: Clone Repository in Container Volume”命令时迭代您的容器。

  1. 从命令面板 (F1) 中的“Dev Containers: Clone Repository in Container Volume”开始。 如果您输入的存储库中没有 `devcontainer.json`,您将被要求选择一个起点。
  2. 根据需要编辑 `.devcontainer` 文件夹的内容。
  3. 使用“Dev Containers: Rebuild Container”试一下。
  4. 如果您看到错误,请在出现的对话框中选择“Open in Recovery Container”。
  5. 在“恢复容器”中根据需要编辑 `.devcontainer` 文件夹的内容。
  6. 使用“Dev Containers: Reopen in Container”,如果您仍然遇到问题,请跳到步骤 4。

使用 Docker Compose

在某些情况下,单个容器环境是不够的。 假设您想将另一个复杂组件添加到您的配置中,例如数据库。 您尝试直接将其添加到 Dockerfile 中,或者您可以通过另一个容器添加它。 幸运的是,Dev Containers 支持 Docker Compose 管理的多容器配置。

您可以:

  1. 使用在现有未修改的 `docker-compose.yml` 中定义的服务。
  2. 创建一个新的 `docker-compose.yml`(或复制一个现有的 `docker-compose.yml`),您用它来开发服务。
  3. 扩展您的现有 Docker Compose 配置 以开发该服务。
  4. 使用单独的 VS Code 窗口 同时处理多个 Docker Compose 定义的服务

**注意:** 当使用 Alpine Linux 容器时,某些扩展可能无法正常工作,因为扩展中的本机代码中有 `glibc` 依赖关系。

VS Code 可以配置为 **自动启动 Docker Compose 文件中特定服务所需的任何容器**。 如果您已经使用命令行启动了已配置的容器,VS Code 将 **附加到您指定的正在运行的服务**。 这使得您的多容器工作流程具有与上面描述的 Docker 镜像和 Dockerfile 工作流程相同的快速设置优势,同时仍然允许您在需要时使用命令行。

要快速入门,请在 VS Code 中 **打开要处理的文件夹**,并在命令面板 (F1) 中运行 **Dev Containers: Add Dev Container Configuration Files...** 命令。

系统将提示您从我们的 第一方和社区索引 中选择一个预定义的容器配置,该配置在一个可过滤列表中根据您的文件夹内容进行排序。 从 VS Code UI 中,您可以选择以下模板之一作为 Docker Compose 的起点

  • 现有 Docker Compose - 包含一组可以添加到现有项目中的文件,这些文件将重用您项目根目录中的 `docker-compose.yml` 文件。
  • Node.js & MongoDB - 一个 Node.js 容器,连接到另一个容器中的 MongoDB 数据库。
  • Python & PostgreSQL - 一个 Python 容器,连接到另一个容器中的 PostgreSQL。
  • Docker-Outside-of-Docker Compose - 包含 Docker CLI,并说明如何通过挂载 Docker Unix 套接字卷来从开发容器内部访问本地 Docker 安装。

在您做出选择后,VS Code 将在文件夹中添加相应的 .devcontainer/devcontainer.json(或 .devcontainer.json)文件。

您也可以手动创建配置。要重用未修改的 Docker Compose 文件,您可以在 .devcontainer/devcontainer.json 中使用 dockerComposeFileservice 属性。

例如

{
  "name": "[Optional] Your project name here",
  "dockerComposeFile": "../docker-compose.yml",
  "service": "the-name-of-the-service-you-want-to-work-with-in-vscode",
  "workspaceFolder": "/default/workspace/path/in/container/to/open",
  "shutdownAction": "stopCompose"
}

有关其他可用属性(如 workspaceFoldershutdownAction)的信息,请参见 devcontainer.json 参考

在您将 .devcontainer/devcontainer.json 文件添加到文件夹后,从命令面板(F1)运行 开发容器:在容器中重新打开 命令(如果您还没有在容器中,则运行 开发容器:在容器中打开文件夹...)。

如果容器尚未运行,VS Code 将在此示例中调用 docker-compose -f ../docker-compose.yml upservice 属性指示 Docker Compose 文件中 VS Code 应连接到的服务,而不是应启动的服务。如果您手动启动了它们,VS Code 将连接到您指定的服务。

您还可以创建一个开发版本的 Docker Compose 文件。例如,如果您有 .devcontainer/docker-compose.devcontainer.yml,您只需更改 devcontainer.json 中的以下行

"dockerComposeFile": "docker-compose.devcontainer.yml"

但是,更好的方法通常是通过 使用另一个 Docker Compose 文件扩展它 来避免复制 Docker Compose 文件。我们将在下一节中介绍 扩展 Docker Compose 文件

为了避免在默认容器命令失败或退出时容器关闭,您可以修改在 devcontainer.json 中指定的服务的 Docker Compose 文件,如下所示

# Overrides default command so things don't shut down after the process ends.
command: /bin/sh -c "while sleep 1000; do :; done"

如果您尚未这样做,您可以使用 Docker Compose 文件中的卷列表 将本地源代码 “绑定”挂载 到容器中。

例如

volumes:
  # Mounts the project folder to '/workspace'. The target path inside the container
  # should match what your application expects. In this case, the compose file is
  # in a sub-folder, so you will mount '..'. You would then reference this path as the
  # 'workspaceFolder' in '.devcontainer/devcontainer.json' so VS Code starts here.
  - ..:/workspace:cached

但是,在 Linux 上,在使用绑定挂载时,您可能需要设置并 指定非 root 用户,否则您创建的任何文件都将是 root 拥有的。有关详细信息,请参阅 在开发容器中添加非 root 用户。要让 VS Code 以不同的用户身份运行,请将以下内容添加到 devcontainer.json

"remoteUser": "your-user-name-here"

如果您希望所有进程都以不同的用户身份运行,请将以下内容添加到 Docker Compose 文件中的相应服务中

user: your-user-name-here

如果您没有为开发创建自定义 Dockerfile,您可能希望在服务的容器中安装其他开发工具,例如 curl。虽然这不如将这些工具添加到容器映像效率高,但您也可以使用 postCreateCommand 属性来实现此目的。

有关安装软件的更多信息,请参见 安装其他软件,有关 postCreateCommand 属性的更多信息,请参见 devcontainer.json 参考

如果您的应用程序使用 C++、Go 或 Rust 或其他使用基于 ptrace 的调试器的语言构建,您还需要将以下设置添加到您的 Docker Compose 文件

# Required for ptrace-based debuggers like C++, Go, and Rust
cap_add:
- SYS_PTRACE
security_opt:
- seccomp:unconfined

首次创建容器后,您需要运行 开发容器:重建容器 命令,以便 devcontainer.json、Docker Compose 文件或相关 Dockerfile 的更新生效。

在 Docker Compose 中使用 localhost

您可以按照 Docker 文档 中的说明,将其他服务添加到您的 docker-compose.yml 文件中。但是,如果您希望在此服务中运行的任何内容都可以在容器的 localhost 上使用,或者您希望在本地转发服务,请确保将以下行添加到服务配置中

# Runs the service on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
network_mode: service:db

您可以在 Node.js 和 MongoDB 示例开发容器 中看到 network_mode: service:db 的示例。

扩展您的 Docker Compose 文件以用于开发

引用现有的部署/非开发重点 docker-compose.yml 有一些潜在的缺点。

例如

  • 如果 Docker Compose 的入口点关闭,它将关闭容器。这对于您在调试时需要重复重启应用程序的情况来说是个问题。
  • 您可能还没有将本地文件系统映射到容器中,或者将端口公开到您想要访问的其他资源(如数据库)。
  • 您可能希望将本地 .ssh 文件夹的内容复制到容器中,或者设置上面 使用 Docker Compose 中描述的 ptrace 选项。

您可以通过使用 多个 docker-compose.yml 文件 扩展整个 Docker Compose 配置来解决这些问题以及类似的问题,这些文件会覆盖或补充您的主文件。

例如,考虑此附加的 .devcontainer/docker-compose.extend.yml 文件

version: '3'
services:
  your-service-name-here:
    volumes:
      # Mounts the project folder to '/workspace'. While this file is in .devcontainer,
      # mounts are relative to the first file in the list, which is a level up.
      - .:/workspace:cached

    # [Optional] Required for ptrace-based debuggers like C++, Go, and Rust
    cap_add:
      - SYS_PTRACE
    security_opt:
      - seccomp:unconfined

    # Overrides default command so things don't shut down after the process ends.
    command: /bin/sh -c "while sleep 1000; do :; done"

该文件还可以根据需要提供其他设置,例如端口映射。要使用它,请按特定顺序引用您的原始 docker-compose.yml 文件以及 .devcontainer/docker-compose.extend.yml 文件

{
  "name": "[Optional] Your project name here",

  // The order of the files is important since later files override previous ones
  "dockerComposeFile": ["../docker-compose.yml", "docker-compose.extend.yml"],

  "service": "your-service-name-here",
  "workspaceFolder": "/workspace",
  "shutdownAction": "stopCompose"
}

然后,VS Code 将在启动任何容器时 自动使用这两个文件。您也可以从命令行手动启动它们,方法如下

docker-compose -f docker-compose.yml -f .devcontainer/docker-compose.extend.yml up

虽然 postCreateCommand 属性允许您在容器中安装其他工具,但在某些情况下,您可能希望为开发提供特定的 Dockerfile。您也可以使用相同的方法来引用专门用于开发的自定义 Dockerfile,而无需修改现有的 Docker Compose 文件。例如,您可以更新 .devcontainer/docker-compose.extend.yml,如下所示

version: '3'
services:
  your-service-name-here:
      # Note that the path of the Dockerfile and context is relative to the *primary*
      # docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile"
      # array). The sample below assumes your primary file is in the root of your project.
      build:
        context: .
        dockerfile: .devcontainer/Dockerfile
      volumes:
        - .:/workspace:cached
      command: /bin/sh -c "while sleep 1000; do :; done"

恭喜!您现在已在 Visual Studio Code 中配置了开发容器。继续阅读以了解如何与团队成员和各种项目共享容器配置。

将配置文件添加到存储库

通过将 devcontainer.json 文件添加到源代码管理中,您可以轻松地为项目共享自定义的开发容器模板。通过将这些文件包含在您的存储库中,任何在 VS Code 中打开您存储库的本地副本的人都会自动被提示在容器中重新打开文件夹,前提是他们已安装开发容器扩展。

Dev container configuration file reopen notification

除了让您的团队使用一致的环境和工具链的优势之外,这也有助于新贡献者或团队成员更快地提高工作效率。首次贡献者将需要更少的指导,并遇到更少与环境设置相关的问题。

添加一个在开发容器中打开的徽章

您还可以添加一个徽章或链接到您的存储库,以便用户可以轻松地在开发容器中打开您的项目。它将在必要时安装开发容器扩展,将存储库克隆到一个容器 中,并启动开发容器。

例如,一个用于打开 https://github.com/microsoft/vscode-remote-try-java 的徽章看起来像这样

[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode-remote-try-java)

您也可以直接包含一个 在开发容器中打开 链接

If you already have VS Code and Docker installed, you can click the badge above or [here](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode-remote-try-java) to get started. Clicking these links will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use.

替代方案:存储库配置文件夹

在某些情况下,您可能希望为一个您无法控制或您更希望不在存储库本身中包含配置的存储库创建配置。为了处理这种情况,您可以在本地文件系统上配置一个位置来存储配置文件,这些文件将根据存储库自动提取。

首先,使用您要用来存储存储库容器配置文件的本地文件夹,更新 开发 > 容器:存储库配置路径 用户设置

在设置编辑器中,您可以搜索“开发容器存储库”以查找该设置

Repository container folders setting

接下来,将 .devcontainer/devcontainer.json(以及相关文件)放在一个镜像存储库远程位置的子文件夹中。例如,如果您想为 github.com/devcontainers/templates 创建配置,您将创建以下文件夹结构

📁 github.com
    📁 devcontainers
        📁 templates
           📁 .devcontainer

一旦就位,在使用任何开发容器命令时,该配置将自动提取。进入容器后,您还可以从命令面板(F1)选择 开发容器:打开容器配置文件 来打开相关的 devcontainer.json 文件并进行进一步编辑。

用于查找配置的路径来自 git remote -v 的输出。如果您在尝试在容器中重新打开文件夹时未找到配置,请查看命令面板(F1)中的日志 开发容器:显示容器日志,以获取已检查的路径列表。

后续步骤