创建开发容器
Visual Studio Code 开发容器扩展允许你将 Docker 容器 用作功能齐全的开发环境。它允许你在容器内打开任何文件夹或存储库,并利用 Visual Studio Code 的所有功能。项目中的 devcontainer.json
文件会告诉 VS Code 如何访问(或创建)具有明确定义工具和运行时堆栈的开发容器。此容器可用于运行应用程序,或提供处理代码库所需的独立工具、库或运行时。
创建开发容器的路径
本文档将介绍在 VS Code 中创建开发容器的步骤
- 创建
devcontainer.json
文件,它描述了 VS Code 应如何启动容器以及连接后应执行的操作。 - 通过使用 Dockerfile 对开发容器进行更改并使其持久化,例如安装新软件。
- 通过 Docker Compose 配置多个容器。
- 在进行更改时,构建开发容器以确保更改生效。
完成上述任一步骤后,你将获得一个功能齐全的开发容器,你可以继续本教程的下一步以添加更多功能,或者停止并开始在你当前的开发环境中工作。
注意:开发容器扩展有一个 开发容器:添加开发容器配置文件... 命令,它允许你从列表中选择预定义的容器配置。如果你希望立即获得一个完整的开发容器,而不是逐步构建
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"
}
你可以更改配置以执行以下操作
- 在容器中安装 Git 等附加工具。
- 自动安装扩展。
- 转发或发布附加端口。
- 设置运行时参数。
- 复用或扩展现有的 Docker Compose 设置。
- 添加更多高级容器配置。
对于此示例,如果你想在容器中安装 代码拼写检查器扩展 并自动转发端口 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
,你的开发容器即可正常工作,你可以连接到并在其中开始开发。使用 开发容器:在容器中重新打开 命令试用一下
运行此命令后,当 VS Code 重新启动时,你将进入一个 Node.js 和 TypeScript 开发容器,其中端口 3000 已转发并安装了 ESLint 扩展。连接后,请注意状态栏左侧的绿色远程指示器,它显示你已连接到你的开发容器
其他开发容器场景
通过 devcontainer.json
文件,你可以
- 启动一个独立容器以隔离你的工具链或加速设置。
- 使用由镜像、Dockerfile 或 Docker Compose 定义的容器部署应用程序。
- 从开发容器内部使用 Docker 或 Kubernetes 生成和部署你的应用程序。
如果 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"
}
}
有关更多详细信息,请参阅开发容器功能规范。
重建
编辑 .devcontainer
文件夹的内容时,你需要重建容器以使更改生效。使用 开发容器:重建容器 命令更新你的容器。
但是,如果你重建容器,则必须重新安装你手动安装的所有内容。为了避免此问题,你可以使用 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) 选择 开发容器:添加开发容器配置文件... 命令,这会将所需文件添加到你的项目作为起点,你可以根据需要进一步自定义。
该命令允许你根据文件夹内容从列表中选择预定义的容器配置
你可以选择的预定义容器配置来自我们的第一方和社区索引,这是开发容器规范的一部分。我们在 devcontainers/templates 仓库中托管了一组模板作为规范的一部分。你可以浏览该仓库的 src
文件夹以查看每个模板的内容。
在使用 开发容器:添加开发容器配置文件... 命令的末尾,将显示可用功能的列表,这些功能是你可以轻松添加到开发容器中的工具和语言。开发容器:配置容器功能 允许你更新现有配置。
你还可以复用现有的 Dockerfile
现在你有了 devcontainer.json
和 Dockerfile,让我们看看编辑容器配置文件的通用流程。
完整配置编辑循环
编辑你的容器配置很容易。由于重建容器会将容器“重置”为其起始内容(你的本地源代码除外),因此如果你编辑容器配置文件(devcontainer.json
、Dockerfile
和 docker-compose.yml
),VS Code 不会自动重建。相反,可以使用几个命令来使编辑配置更容易。
以下是使用这些命令的典型编辑循环
- 在命令面板 (F1) 中从 开发容器:添加开发容器配置文件... 命令开始。
- 根据需要编辑
.devcontainer
文件夹的内容。 - 使用 开发容器:在容器中重新打开 命令试用。
- 如果出现错误,在显示的对话框中选择 本地打开文件夹。
- 窗口重新加载后,控制台中将显示 构建日志 的副本,以便你可以调查问题。根据需要编辑
.devcontainer
文件夹的内容。(你也可以使用 开发容器:显示容器日志 命令再次查看日志,如果你关闭了它的话。) - 运行 开发容器:重建并在容器中重新打开,如果需要,跳到步骤 4。
如果你已经成功构建,连接到容器后仍然可以根据需要编辑 .devcontainer
文件夹的内容,然后从命令面板 (F1) 中选择 开发容器:重建容器 以使更改生效。
使用 开发容器:在容器卷中克隆仓库 命令时,你也可以迭代你的容器。
- 在命令面板 (F1) 中从 开发容器:在容器卷中克隆仓库 命令开始。如果你输入的仓库中没有
devcontainer.json
文件,系统会要求你选择一个起点。 - 根据需要编辑
.devcontainer
文件夹的内容。 - 使用 开发容器:重建容器 命令试用。
- 如果出现错误,在显示的对话框中选择 在恢复容器中打开。
- 在这个“恢复容器”中根据需要编辑
.devcontainer
文件夹的内容。 - 使用 开发容器:在容器中重新打开 命令,如果仍然遇到问题,跳到步骤 4。
使用 Docker Compose
在某些情况下,单个容器环境是不够的。例如,你可能想向配置中添加另一个复杂组件,例如数据库。你可以尝试直接将其添加到 Dockerfile,或者通过附加容器添加。幸运的是,开发容器支持 Docker Compose 管理的多容器配置。
你可以选择
- 使用现有、未修改的
docker-compose.yml
文件中定义的服务。 - 创建新的
docker-compose.yml
文件(或复制现有文件)用于开发服务。 - 扩展现有的 Docker Compose 配置以开发服务。
- 使用单独的 VS Code 窗口同时使用 Docker Compose 定义的多个服务。
注意:使用 Alpine Linux 容器时,由于扩展中本机代码存在
glibc
依赖项,某些扩展可能无法工作。
VS Code 可以配置为自动启动 Docker Compose 文件中特定服务所需的任何容器。如果你已经使用命令行启动了配置的容器,VS Code 将转而附加到你指定的正在运行的服务。这为你的多容器工作流提供了与上述 Docker 镜像和 Dockerfile 工作流相同的快速设置优势,同时仍然允许你根据需要使用命令行。
为了快速入门,在 VS Code 中打开你想要使用的文件夹,并在命令面板 (F1) 中运行 开发容器:添加开发容器配置文件... 命令。
系统会提示你从我们的第一方和社区索引中选择一个预定义的容器配置,列表可筛选并根据文件夹内容排序。从 VS Code UI 中,你可以选择以下模板之一作为 Docker Compose 的起点
- 现有 Docker Compose - 包含一组文件,你可以将其放入现有项目中,这些文件将重用项目根目录中的
docker-compose.yml
文件。 - Node.js 和 MongoDB - 连接到不同容器中 MongoDB 数据库的 Node.js 容器。
- Python 和 PostgreSQL - 连接到不同容器中 PostgreSQL 的 Python 容器。
- Docker-Outside-of-Docker Compose - 包含 Docker CLI,并演示了如何通过卷挂载 Docker Unix 套接字从开发容器内部访问本地 Docker 安装。
做出选择后,VS Code 会将相应的 .devcontainer/devcontainer.json
(或 .devcontainer.json
)文件添加到文件夹中。
你也可以手动创建配置。要复用未修改的 Docker Compose 文件,可以在 .devcontainer/devcontainer.json
中使用 dockerComposeFile
和 service
属性。
例如
{
"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"
}
有关其他可用属性(例如 workspaceFolder
和 shutdownAction
)的信息,请参阅 devcontainer.json 参考。
将 .devcontainer/devcontainer.json
文件添加到文件夹后,从命令面板 (F1) 运行 开发容器:在容器中重新打开 命令(如果你尚未在容器中,则运行 开发容器:在容器中打开文件夹... 命令)。
如果容器尚未运行,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 文件。
为避免在默认容器命令失败或退出时关闭容器,你可以按如下方式修改 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"
同一个文件可以根据需要提供附加设置,例如端口映射。要使用它,除了 .devcontainer/docker-compose.extend.yml
之外,还需按特定顺序引用你的原始 docker-compose.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 Containers 扩展(如果需要),将仓库克隆到容器卷中,并启动开发容器。
例如,用于打开 https://github.com/microsoft/vscode-remote-try-java 的徽章如下所示
[](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.
替代方案:仓库配置文件夹
在某些情况下,您可能希望为不受您控制或您不希望在仓库本身中包含配置的仓库创建配置。为了处理这种情况,您可以在本地文件系统上配置一个位置来存储配置文件,这些文件将根据仓库自动被拾取。
首先,使用您想要用于存储仓库容器配置文件的本地文件夹更新开发容器 > 容器:仓库配置路径 用户设置。
在设置编辑器中,您可以搜索“dev containers repo”来找到该设置。
接下来,将您的 .devcontainer/devcontainer.json
(及相关文件)放置在一个子文件夹中,该子文件夹镜像仓库的远程位置。例如,如果您想为 github.com/devcontainers/templates
创建配置,您将创建以下文件夹结构
📁 github.com
📁 devcontainers
📁 templates
📁 .devcontainer
配置到位后,在使用任何 Dev Containers 命令时,该配置将自动被拾取。进入容器后,您还可以从命令面板 (F1) 中选择开发容器:打开容器配置文件来打开相关的 devcontainer.json
文件并进行进一步编辑。
用于查找配置的路径是从 git remote -v
的输出中派生的。如果在容器中尝试重新打开文件夹时未找到配置,请在命令面板 (F1) 中检查日志 开发容器:显示容器日志,以查看检查过的路径列表。
后续步骤
- 连接到正在运行的容器 - 连接到一个已经运行的 Docker 容器。
- 高级容器 - 查找高级容器场景的解决方案。
- devcontainer.json 参考 - 查看
devcontainer.json
模式。