现已发布!阅读有关 11 月份的新功能和修复的信息。

使用 VS Code 检查容器

2019 年 10 月 31 日,作者:Bowden Kelly,@bowdenk7

在开发容器化应用程序时,通常会尝试通过使用 docker exec --it {containerID} /bin/sh 将 shell 附加到正在运行的容器来调试构建和运行时问题。

Running docker exec command

此技术允许你通过命令行检查容器环境,但它不提供一套丰富的工具来诊断问题。

在这篇文章中,我们将了解如何将 Visual Studio Code 附加到你的容器,以便你可以使用 VS Code 的全部功能,包括调试,来检查容器、找出问题所在并修复它。

今年 5 月推出的 开发容器扩展允许你将本地 VS Code 连接到容器主机,同时保留所有个性化设置、主题和键盘绑定。

先决条件

此博客文章假定你已安装 Docker DesktopVisual Studio Code。你还需要 开发容器扩展。要安装开发容器扩展,请打开“扩展”视图(⇧⌘X(Windows、Linux Ctrl+Shift+X),搜索“开发容器”,选择“安装”,如果提示,请重启 VS Code。

应用程序

我们首先需要一个可以在容器中运行的应用程序。如果你有一个,那就太好了!你可以跳过此步骤。如果没有,你可以克隆这个简单的 Node.js Express 应用程序。

注意:你不需要在本地安装 Node.js,我们将在容器中运行此应用程序!

git clone https://github.com/microsoft/vscode-express-sample.git

此应用程序有一个简单的 Dockerfile,它基于 Node 10 映像,以及一个 docker-compose.yml 文件,我们将使用它来运行映像、公开适当的端口并将本地文件系统映射到容器中。我们使用 –inspect 标志运行 Node,以便我们像在本地运行时一样调试应用程序。在实际应用程序中,你可能需要一个单独的 Docker Compose 文件用于生产部署。

注意:你不需要 Docker Compose 文件,你也可以附加到使用单个 Dockerfile 创建的容器。

构建和运行

要构建和运行应用程序,我们首先安装依赖项,然后从终端/命令提示符运行 docker-compose up。这将下载 Node 基本映像、复制依赖项并启动容器。

docker-compose up

如果一切正常,你应该看到类似这样的输出

docker-compose up output

而且,你应该能够导航到 https://127.0.0.1:3000 并看到以下内容

Welcome to Express web page

附加到容器

我们现在可以使用开发容器扩展附加到我们正在运行的容器、检查环境和调试应用程序。

在活动栏中选择“远程资源管理器”,以查看可以在“其他容器”部分中附加到的正在运行的容器列表。找到我们刚刚启动的容器,它的名称为“express_server_1”,然后使用“连接到容器”按钮附加到它。该容器现在应该显示在“远程资源管理器”的“已附加容器”部分中。

Attached Containers in the Remote Explorer

这将启动一个新的 VS Code 窗口(实例),并在右下角显示以下通知。

Installing Dev Container notification

在此期间,VS Code 将在你的应用程序正在运行的容器内安装一个 VS Code 服务器实例。要查看有关此安装步骤的更多详细信息和进度,你可以选择通知中显示的“详细信息”链接。安装 VS Code 服务器后,你的本地 VS Code 客户端将连接到远程 VS Code 服务器。结果是你的本地 VS Code 实例(包含你的所有设置、主题和键盘绑定)连接到与你的应用程序一起在容器内运行的“后端”。

Dev Containers architecture diagram

连接完成后,你应该会看到一个新的 VS Code 窗口,左下角有一个绿色指示器,指示此 VS Code 实例正在远程上下文中运行。如果单击该指示器,你将看到与当前远程上下文相关的命令下拉列表。

Remote context shown in the Status bar

让我们继续,通过选择“打开文件夹”按钮并导航到 /usr/src/app 来打开我们的应用程序。请注意,“打开文件夹”对话框显示的是正在运行的容器中的文件系统,而不是本地文件系统

Open Folder dialog show container file system

打开你的源文件夹后,你会注意到一个文件已在编辑器中打开,文件名为 express-server.json。此名称源自你附加到的容器映像名称。在我们的示例中,docker-compose 创建映像名称“express_server”,该名称源自 docker-compose.yml 文件中定义的文件夹名称 express 和服务名称 server。此文件是与你的映像关联的配置文件,它将在你附加到基于此映像的容器时记住配置设置。如果你没有启用自动保存,则需要确保保存此文件。现在,在以后的会话中,当你附加到此映像时,VS Code 将重新打开此源文件夹。

注意:你可以通过从命令面板(⇧⌘P(Windows、Linux Ctrl+Shift+P)运行命令“打开容器配置文件”来查看当前开发容器的此文件。

express-server.json file contents

此时,VS Code 看起来与普通的本地 VS Code 窗口相同。

VS Code running in a container

你可以执行在普通的本地 VS Code 上下文中可以执行的任何操作。

例如,打开 app.js。右键单击第 8 行并执行“查找所有引用”以查找 usersRouter 的所有用法。任何编辑都会持久保存到本地磁盘,因为我们使用 docker-compose 文件将本地文件系统安装到容器中。

在容器内调试

为了进一步说明开发容器与本地环境有多么相似,让我们附加一个调试器。我们在 docker-compose.yaml 中使用 –inspect 参数启动了我们的 Node 应用程序,因此我们所要做的就是将调试器附加到该进程。

在命令面板(⇧⌘P(Windows、Linux Ctrl+Shift+P)中,搜索并选择“调试:附加到 Node 进程”。容器内部可能会运行多个 Node 进程。我们想要运行我们应用程序的进程,因此选择显示 bin/www 的进程。

Node process picker list

接下来,打开 index.js 并通过单击装订线或按 F9 在第 6 行设置一个断点

res.render('index', { title: 'Express' });

现在在浏览器中转到 https://127.0.0.1:3000,并查看断点是否按预期触发!

安装扩展

就像普通的 VS Code 实例一样,你可以在附加到开发容器时安装和使用扩展。

根据扩展的类型,它可以运行在客户端或远程 VS Code 服务器上的容器中。主要基于 UI 的扩展(如主题和代码片段)保留在客户端,而所有其他扩展都安装在容器中。这使你可以在每个环境中工作时仅使用所需的扩展,同时在所有环境中保持一致的 UI。

如果你打开“扩展”视图(⇧⌘X(Windows、Linux Ctrl+Shift+X),你将看到你本地安装的扩展列表以及你当前容器实例中安装的扩展列表。需要在容器中安装的本地安装的扩展(如下面的 Azure 帐户扩展)将显示为灰色。

Remote Extensions view

让我们通过在“扩展”视图中键入“gitlens”并选择“安装在附加的容器中”来安装 GitLens 扩展。

Search for GitLens

这将提示你重启 VS Code,这样做后,你会短暂看到“正在安装开发容器”通知,因为容器和 VS Code 服务器会使用我们新安装的扩展重启。

你还会注意到我们之前看到的容器配置文件已再次打开,并使用一个新属性进行了更新,该属性列出了我们每次附加到此映像时要安装的扩展。

{
  "workspace": "/usr/src/app",
  "extensions": ["eamodio.gitlens"]
}

现在打开任何文件,选择一行代码,并注意你已获得 GitLens 提供的内联 Git 信息!

GitLens information shown in the editor

清理

完成后,你可以从命令面板运行“关闭远程连接”命令,或直接关闭 VS Code 窗口来终止远程连接。

现在从终端/命令提示符运行 docker-compose down 以停止正在运行的容器。这将释放内存并释放任何已使用的端口。

docker-compose down

现在你已准备好启动另一个容器并处理另一个项目!

后续步骤

在这篇博客文章中,我们介绍了如何使用开发容器扩展附加到你现有的容器化应用程序。

你也可以创建一个 devcontainer.json 文件,该文件描述你想要创建或附加到的开发环境,并与你的项目一起保存,以便与你的团队成员共享。

其他有用的资源包括完整的 在容器内开发 文档、高级容器配置,以及我们关于使用 Dev Containers 扩展构建隔离开发环境的 入门教程

祝你远程编码愉快!

Bowden Kelly,VS Code 项目经理 @bowdenk7