创建 Dev Containers

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

创建 Dev Containers 的路径

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

  1. 创建一个devcontainer.json,它描述 VS Code 应如何启动容器以及连接后要执行的操作。
  2. 通过使用 Dockerfile 对 Dev Containers 进行并保留更改,例如安装新软件。
  3. 通过 Docker Compose 配置多个容器。
  4. 当您进行更改时,构建您的 Dev Containers 以确保更改生效。

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

注意: Dev Containers 扩展具有 Dev Containers :添加 Dev Containers 配置文件...命令,可让您从列表中选择预定义的容器配置。devcontainer.json如果您希望立即拥有一个完整的 Dev Containers ,而不是逐步构建Dockerfile,则可以跳至自动化 Dev Containers 创建

创建 devcontainer.json 文件

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

您可以使用图像作为devcontainer.json. 映像就像一个预装了各种工具和操作系统的迷你磁盘驱动器。您可以从容器注册表中提取映像,容器注册表是存储映像的存储库的集合。下面是一个devcontainer.json使用预构建的 TypeScript 和 Node.js VS 代码 Dev Containers 映像的简单示例:

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

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

对于此示例,如果您想将代码拼写检查器扩展安装到您的容器中并自动转发端口 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"作为. 当使用 devcontainer.json 进行预构建时,这种情况会自动发生,您可以在预构建部分阅读更多相关信息。mcr.microsoft.com/devcontainers/typescript-node

通过上述操作devcontainer.json,您的 Dev Containers 就可以正常运行了,您可以连接到其中并开始在其中进行开发。使用Dev Containers: Reopen in Container命令尝试一下:

使用 Dev Containers 命令列表快速选择

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

连接到 Dev Containers 的 VS Code 实例

其他 Dev Containers 场景

通过devcontainer.json文件,您可以:

如果devcontainer.json支持的工作流程不能满足您的需求,您还可以附加到已经运行的容器

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

安装附加软件

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

大多数容器镜像都基于 Debian 或 Ubuntu,其中aptapt-get命令用于安装新软件包。您可以在 Ubuntu 的文档中了解有关该命令的更多信息。Alpine 映像包含类似的apk命令,而 CentOS/RHEL/Oracle SE/Fedora 映像使用yum更新版本dnf

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

例如:

# 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

您还可以使用"features"中的属性devcontainer.json来安装预定义功能集甚至您自己的功能中的工具和语言。

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

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

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

重建

编辑文件夹的内容时.devcontainer,您需要重新构建才能使更改生效。使用 Dev Containers :重建容器命令来更新您的容器。

但是,如果您重建容器,则必须重新安装手动安装的任何内容。为了避免此问题,您可以使用postCreateCommand中的属性devcontainer.json或自定义Dockerfile.

自定义Dockerfile将受益于 Docker 的构建缓存,并导致比postCreateCommand. 但是,Dockerfile在创建 Dev Containers 和安装工作区文件夹之前运行,因此无权访问工作区文件夹中的文件。ADockerfile最适合安装独立于工作区文件的包和工具。

postCreateCommand创建容器后,这些操作就会运行,因此您还可以使用该属性来运行命令,例如npm install或在源代码树中执行 shell 脚本(如果您已安装它)。

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

您还可以使用交互式 bash shell,以便.bashrc选择您的 shell,自动根据您的环境自定义 shell:

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

-i如果不使用将 shell 置于交互模式,像 NVM 这样的工具将无法工作:

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

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

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

更有效的做法是使用 Dockerfile,而不是直接在 中引用映像或通过或devcontainer.json安装软件。postCreateCommandpostStartCommand

Dockerfile

Dockerfile 也将存在于该.devcontainer文件夹中。您可以将image属性替换devcontainer.jsondockerfile

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

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

  "forwardPorts": [3000]
}

当您进行更改(例如安装新软件)时,即使在重建 Dev Containers 后,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导出可避免您继续使用容器时出现警告。

自动创建 Dev Containers

无需.devcontainer手动创建,从命令面板 ( F1 ) 选择 Dev Containers :添加 Dev Containers 配置文件...命令会将所需的文件添加到您的项目作为起点,您可以根据需要进一步自定义这些文件。

该命令允许您根据文件夹的内容从列表中选择预定义的容器配置:

添加 Dev Containers 配置

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

在使用 Dev Containers :添加 Dev Containers 配置文件...结束时,您将看到可用功能列表,这些功能是您可以轻松放入 Dev Containers 中的工具和语言。 Dev Containers :配置容器功能允许您更新现有配置。

命令面板中的 Dev Containers 功能

您还可以重用现有的 Dockerfile:

选择 Dockerfile

现在您已经有了一个devcontainer.jsonDockerfile,让我们看看编辑容器配置文件的一般过程。

完整配置编辑循环

编辑容器配置很容易。由于重建容器会将容器“重置”为其起始内容(本地源代码除外),因此如果您编辑容器配置文件( 、devcontainer.jsonDockerfile),docker-compose.ymlVS Code 不会自动重建。相反,有几个命令可用于更轻松地编辑配置。

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

容器编辑循环图

  1. 从 Dev Containers 开始在命令面板 ( F1 )中添加 Dev Containers 配置文件...。
  2. .devcontainer根据需要编辑文件夹的内容。
  3. 尝试使用 Dev Containers :在容器中重新打开
  4. 如果看到错误,请在出现的对话框中选择本地打开文件夹。
  5. 窗口重新加载后,构建日志的副本将出现在控制台中,以便您可以调查问题。.devcontainer根据需要编辑文件夹的内容。(如果关闭日志,您还可以使用 Dev Containers :显示容器日志命令再次查看日志。)
  6. 运行 Dev Containers :在容器中重建并重新打开,并根据需要跳转到步骤 4。

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

使用Dev Containers: Clone Repository in Container Volume命令时,您还可以迭代容器。

  1. 从 Dev Containers 开始:在命令面板 ( F1 ) 的容器卷中克隆存储库。如果您输入的存储库中没有,系统会要求您选择一个起点。devcontainer.json
  2. .devcontainer根据需要编辑文件夹的内容。
  3. 尝试使用 Dev Containers :重建容器
  4. 如果您看到错误,请在出现的对话框中选择“在恢复容器中打开” 。
  5. 根据需要在此“恢复容器”中编辑文件夹的内容.devcontainer
  6. 使用 Dev Containers :在容器中重新打开,如果仍然遇到问题,请跳转到步骤 4。

使用 Docker 撰写

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

您可以:

  1. 使用现有的、未经修改的docker-compose.yml.
  2. 创建一个新的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 :添加 Dev Containers 配置文件...命令。

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

  • 现有 Docker Compose - 包括一组文件,您可以将这些文件放入现有项目中,这些项目将重用docker-compose.yml项目根目录中的文件。
  • Node.js 和 MongoDB - 连接到不同容器中的 MongoDB 数据库的 Node.js 容器。
  • Python 和 PostgreSQL - 连接到不同容器中的 PostgreSQL 的 Python 容器。
  • Docker-from-Docker Compose - 包括 Docker CLI 并说明如何使用它通过卷安装 Docker Unix 套接字从 Dev Containers 内部访问本地 Docker 安装。

做出选择后,VS Code 会将适当的.devcontainer/devcontainer.json(或.devcontainer.json)文件添加到文件夹中。

您还可以手动创建配置。要重新使用未修改的 Docker Compose 文件,您可以dockerComposeFile使用.service.devcontainer/devcontainer.json

例如:

{
  "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"
}

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

将文件添加.devcontainer/devcontainer.json到文件夹后,从命令面板 ( F1 ) 运行 Dev Containers :在容器中重新打开命令(或 Dev Containers :在容器中打开文件夹...,如果您尚未位于容器中)。

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

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

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

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

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

# 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 用户添加到 Dev Containers 。要让 VS Code 以其他用户身份运行,请将其添加到devcontainer.json

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

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

user: your-user-name-here

如果您不创建自定义 Dockerfile 进行开发,您可能需要安装其他开发人员工具,例如curl在服务的容器内安装。虽然比将这些工具添加到容器映像效率低,但您也可以使用该postCreateCommand属性来实现此目的。

有关安装软件的详细信息,请参阅安装其他软件;有关该属性的详细信息,请参阅 devcontainer.json 参考postCreateCommand

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

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

首次创建容器后,您需要运行Dev Containers: Rebuild Container命令以使 Docker Compose 文件或相关 Dockerfile 的更新devcontainer.json生效。

在 Docker Compose 中使用 localhost

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

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

network_mode: service:db您可以在Node.js 和 MongoDB 示例 Dev Containers 中查看示例。

扩展 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/devcontainer.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 中配置了 Dev Containers 。继续阅读以了解如何在团队成员和各种项目之间共享容器配置。

将配置文件添加到存储库

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

 Dev Containers 配置文件重新打开通知

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

添加在 Dev Containers 中打开徽章

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

例如,打开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)

您还可以open in dev container直接添加链接:

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.

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

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

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

在设置编辑器中,您可以搜索“devContainersrepo”来查找设置:

存储库容器文件夹设置

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

???? github.com
    ???? devcontainers
        ???? templates
           ???? .devcontainer

一旦到位,使用任何 Dev Containers 命令时都会自动获取配置。进入容器后,您还可以从命令面板 ( F1 ) 中选择 Dev Containers :打开容器配置文件以打开相关文件并进行进一步编辑。devcontainer.json

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

下一步