现已发布!了解 11 月份的新功能和修复。

使用 Docker Compose

Docker Compose 提供了一种编排协同工作的多个容器的方法。示例包括处理请求的服务和前端网站,或者使用 Redis 缓存等支持功能的服务。如果你的应用程序开发使用微服务模型,则可以使用 Docker Compose 将应用程序代码分解为多个独立运行的服务,这些服务使用 Web 请求进行通信。本文可帮助你为应用程序启用 Docker Compose,无论是 Node.js、Python 还是 .NET,还可以帮助你在 Visual Studio Code 中配置这些场景的调试。

此外,对于单容器场景,使用 Docker Compose 提供了一种独立于工具的配置,而单个 Dockerfile 不会提供这种配置。可以在 docker-compose YML 文件中声明容器的卷挂载、端口映射和环境变量等配置设置。

若要在 VS Code 中使用 Docker 扩展使用 Docker Compose,你应该已经熟悉 Docker Compose 的基础知识。

向项目添加 Docker Compose 支持

如果你已经有一个或多个 Dockerfile,可以通过打开 命令面板⇧⌘P(Windows、Linux Ctrl+Shift+P),然后使用 Docker:向工作区添加 Docker Compose 文件命令来添加 Docker Compose 文件。按照提示操作。

你可以在添加 Dockerfile 的同时向工作区添加 Docker Compose 文件,方法是打开 命令面板⇧⌘P(Windows、Linux Ctrl+Shift+P),然后使用 Docker:向工作区添加 Docker 文件命令。系统会询问你是否要添加 Docker Compose 文件。如果你想保留现有的 Dockerfile,请在系统提示覆盖 Dockerfile 时选择

Docker 扩展会将 docker-compose.yml 文件添加到你的工作区。此文件包含按预期在生产环境中启动容器的配置。在某些情况下,还会生成一个 docker-compose.debug.yml。此文件提供了一种用于启动的简化模式,该模式可以启用调试器。

Screenshot of project with docker-compose files

VS Code Docker 扩展生成的文件可以直接使用,但你也可以自定义这些文件以针对你的场景进行优化。然后,你可以使用 Docker Compose Up 命令(右键单击 docker-compose.yml 文件,或在 命令面板中找到该命令)以一次启动所有内容。你还可以从 VS Code 中的命令提示符或终端窗口使用 docker-compose up 命令来启动容器。有关如何配置 Docker Compose 行为以及可用的命令行选项,请参阅 Docker Compose 文档

使用 docker-compose 文件,你现在可以在 docker-compose 文件中指定端口映射,而不是在 .json 配置文件中指定。有关示例,请参阅 Docker Compose 文档

提示:使用 Docker Compose 时,不要指定主机端口。而是让 Docker 选择一个随机可用的端口以自动避免端口冲突问题。

向项目添加新容器

如果要添加另一个应用程序或服务,可以再次运行 向工作区添加 Docker Compose 文件,然后选择覆盖现有的 docker-compose 文件,但你将丢失这些文件中的任何自定义设置。如果要保留对 compose 文件所做的更改,可以手动修改 docker-compose.yml 文件以添加新服务。通常,你可以复制现有服务部分,将其粘贴以创建新条目,然后根据新服务更改名称。

你可以再次运行 向工作区添加 Docker 文件命令,以生成新应用程序的 Dockerfile。虽然每个应用程序或服务都有自己的 Dockerfile,但每个工作区通常只有一个 docker-compose.yml 和一个 docker-compose.debug.yml 文件。

在 Python 项目中,Dockerfile.dockerignoredocker-compose*.yml 文件都位于工作区的根文件夹中。当你添加另一个应用程序或服务时,请将 Dockerfile 移动到该应用程序的文件夹中。

在 Node.js 项目中,Dockerfile.dockerignore 文件将位于该服务的 package.json 旁边。

对于 .NET,当你创建 Docker Compose 文件时,已经设置了文件夹结构以处理多个项目,.dockerignoredocker-compose*.yml 放置在工作区根目录中(例如,如果项目位于 src/project1 中,则文件位于 src 中),因此,当你添加另一项服务时,你会在一个文件夹中创建另一个项目,比如 project2,并按照先前所述重新创建或修改 docker-compose 文件。

调试

首先,请参阅目标平台的调试文档,了解使用 VS Code 在容器中进行调试的基础知识

如果要在 Docker Compose 中进行调试,请使用前一部分中所述的两个 Docker Compose 文件之一运行命令 Docker Compose Up,然后使用相应的 附加启动配置进行附加。直接使用正常的启动配置启动不会使用 Docker Compose。

创建一个 附加 启动配置。这是 launch.json 中的一个部分。此过程主要为手动操作,但在某些情况下,Docker 扩展可以通过添加一个预配置的启动配置来提供帮助,您可以将其用作模板并进行自定义。以下部分介绍了每个平台(Node.js、Python 和 .NET)的流程。

Node.js

  1. 调试 选项卡上,选择 配置 下拉菜单,选择 新建配置,然后选择 Docker Attach 配置模板 Node.js Docker 附加 (预览)

  2. docker-compose.debug.yml 中配置调试端口。此端口是在创建文件时设置的,因此您可能不需要更改它。在下面的示例中,主机和容器上的调试都使用端口 9229。

     version: '3.4'
    
     services:
       node-hello:
         image: node-hello
         build: .
         environment:
           NODE_ENV: development
         ports:
           - 3000
           - 9229:9229
         command: node --inspect=0.0.0.0:9229 ./bin/www
    
  3. 如果您有多个应用程序,则需要更改其中一些应用程序的端口,以便每个应用程序都有一个唯一的端口。您可以在 launch.json 中指向正确的调试端口,并保存该文件。如果省略此步骤,端口将自动选择。

    以下是一个显示 Node.js 启动配置 - 附加 的示例

     "configurations": [
         {
             "type": "node",
             "request": "attach",
             "name": "Docker: Attach to Node",
             "remoteRoot": "/usr/src/app",
             "port": 9229 // Optional; otherwise inferred from the docker-compose.debug.yml.
         },
         // ...
     ]
    
  4. 完成编辑 附加 配置后,保存 launch.json,然后选择新的启动配置作为活动配置。在 调试 选项卡中,在 配置 下拉菜单中找到新配置。

    Screenshot of Configuration dropdown

  5. 右键单击 docker-compose.debug.yml 文件,然后选择 Compose Up

  6. 当您附加到公开返回 HTML 的 HTTP 端点的服务时,Web 浏览器不会自动打开。要在浏览器中打开应用程序,请在侧边栏中选择容器,右键单击并选择 在浏览器中打开。如果配置了多个端口,系统会要求您选择端口。

  7. 以通常的方式启动调试器。在 调试 选项卡中,选择绿色箭头(启动 按钮)或使用 F5

Python

对于使用 Docker Compose 进行 Python 调试,请按照以下步骤操作

  1. 调试 选项卡上,选择 配置 下拉菜单,选择 新建配置,选择 Python 调试器,然后选择 远程附加 配置模板。

    Screenshot of Python Remote Attach

  2. 系统会提示您选择要用于调试的主机(例如,localhost)和端口。Python 的默认调试端口为 5678。如果您有多个应用程序,则需要更改其中一个应用程序的端口,以便每个应用程序都有一个唯一的端口。您可以在 launch.json 中指向正确的调试端口,并保存该文件。如果省略此步骤,端口将自动选择。

         "configurations": [
         {
            "name": "Python Debugger: Remote Attach",
            "type": "debugpy",
            "request": "attach",
            "port": 5678,
            "host": "localhost",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "/app"
                }
            ]
        }
    
  3. 完成编辑 附加 配置后,保存 launch.json。导航到 调试 选项卡,然后选择 Python 调试器:远程附加 作为活动配置。

  4. 如果您已经有一个有效的 Dockerfile,我们建议运行命令 Docker: 将 Docker Compose 文件添加到工作区。这将创建一个 docker-compose.yml 文件和一个 docker-compose.debug.yml 文件,该文件将卷映射并在容器中启动 Python 调试器。如果您还没有 Dockerfile,我们建议运行 Docker: 将 Docker 文件添加到工作区 并选择 以包含 Docker Compose 文件。

    注意:默认情况下,当使用 Docker: 将 Docker 文件添加到工作区 时,选择 Django 和 Flask 选项将搭建一个为 Gunicorn 配置的 Dockerfile。请按照 容器中的 Python 快速入门 中的说明操作,以确保在继续操作之前正确配置它。

  5. 右键单击 docker-compose.debug.yml 文件(如下所示),然后选择 Compose Up

    version: '3.4'
    
    services:
      pythonsamplevscodedjangotutorial:
        image: pythonsamplevscodedjangotutorial
        build:
          context: .
          dockerfile: ./Dockerfile
        command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 manage.py runserver 0.0.0.0:8000 --nothreading --noreload"]
        ports:
          - 8000:8000
          - 5678:5678
    
  6. 构建并运行容器后,通过按 F5 并选择 Python 调试器:远程附加 启动配置来附加调试器。

    Screenshot of debugging in Python

    注意: 如果您想将 Python 调试器导入到特定文件中,可以在 debugpy README 中找到更多信息。

  7. 当您附加到公开 HTTP 端点并返回 HTML 的服务时,Web 浏览器可能不会自动打开。要在浏览器中打开应用程序,请在 Docker Explorer 中右键单击容器,然后选择 在浏览器中打开。如果配置了多个端口,系统会要求您选择端口。

    Screenshot - Open in Browser

    您现在正在调试容器中运行的应用程序。

.NET

  1. 调试 选项卡上,选择 配置 下拉菜单,选择 新建配置,然后选择 Docker Attach 配置模板 .NET Core Docker 附加 (预览)

  2. VS Code 尝试使用默认路径将 vsdbg 从主机复制到目标容器。您还可以在 附加 配置中提供现有 vsdbg 实例的路径。

     "netCore": {
         "debuggerPath": "/remote_debugger/vsdbg"
     }
    
  3. 完成编辑 附加 配置后,保存 launch.json,然后选择新的启动配置作为活动配置。在 调试 选项卡中,在 配置 下拉菜单中找到新配置。

  4. 右键单击 docker-compose.debug.yml 文件,然后选择 Compose Up

  5. 当您附加到公开返回 HTML 的 HTTP 端点的服务时,Web 浏览器不会自动打开。要在浏览器中打开应用程序,请在侧边栏中选择容器,右键单击并选择 在浏览器中打开。如果配置了多个端口,系统会要求您选择端口。

  6. 以通常的方式启动调试器。在 调试 选项卡中,选择绿色箭头(启动 按钮)或使用 F5

    Screenshot of starting debugging

  7. 如果您尝试附加到在容器中运行的 .NET 应用程序,您会看到一个提示,要求您选择应用程序的容器。

    Screenshot of container selection

    要跳过此步骤,请在 launch.json 中的 附加 配置中指定容器名称

        "containerName": "Your ContainerName"
    

    接下来,系统会询问您是否要将调试器 (vsdbg) 复制到容器中。选择

    Screenshot of debugger prompt

如果一切配置正确,调试器应该会附加到您的 .NET 应用程序。

Screenshot of debug session

卷挂载

默认情况下,Docker 扩展不会为调试组件执行任何卷挂载。在 .NET 或 Node.js 中不需要这样做,因为所需的组件内置于运行时。如果您的应用程序需要卷挂载,请使用 docker-compose*.yml 文件中的 volumes 标签指定它们。

volumes:
    - /host-folder-path:/container-folder-path

具有多个 Compose 文件的 Docker Compose

工作区可以有多个 docker-compose 文件来处理不同的环境,如开发、测试和生产。配置的内容可以拆分为多个文件。例如,一个基本 compose 文件,用于定义所有环境的通用信息,以及单独的覆盖文件,用于定义特定于环境的信息。当这些文件作为输入传递给 docker-compose 命令时,它会将这些文件合并为一个配置。默认情况下,Docker: Compose Up 命令将单个文件作为输入传递给 compose 命令,但是您可以使用 命令自定义 自定义 compose up 命令以传递多个文件。或者,您可以使用 自定义任务 来调用带有所需参数的 docker-compose 命令。

注意:如果您的工作区有 docker-compose.ymldocker-compose.override.yml 且没有其他 compose 文件,则将不带输入文件调用 docker-compose 命令,并且它会隐式使用这些文件。在这种情况下,无需进行自定义。

命令自定义

命令自定义 提供了多种方式来根据您的要求自定义 compose up 命令。以下是 compose up 命令的一些示例命令自定义。

基本文件和覆盖文件

假设您的工作区有一个基本 compose 文件 (docker-compose.yml) 和每个环境的覆盖文件 (docker-compose.dev.yml, docker-compose.test.ymldocker-compose.prod.yml),并且您始终使用基本文件和一个覆盖文件运行 docker compose up。在这种情况下,可以按照以下示例自定义 compose up 命令。当调用 compose up 命令时,${configurationFile} 将被替换为选定的文件。

"docker.commands.composeUp": [
    {
        "label": "override",
        "template": "docker-compose -f docker-compose.yml ${configurationFile}  up -d --build",
    }
]

模板匹配

假设您为每个环境使用不同的输入文件集。您可以定义多个带有正则表达式匹配的模板,并且选定的文件名将与此 match 属性进行匹配,并且将使用相应的模板。

"docker.commands.composeUp": [
    {
        "label": "dev-match",
        "template": "docker-compose -f docker-compose.yml -f docker-compose.debug.yml -f docker-compose.dev.yml up -d --build",
        "match": "dev"
    },
    {
        "label": "test-match",
        "template": "docker-compose -f docker-compose.yml -f docker-compose.debug.yml -f docker-compose.test.yml up -d --build",
        "match": "test"
    },
    {
        "label": "prod-match",
        "template": "docker-compose -f docker-compose.yml -f docker-compose.release.yml -f docker-compose.prod.yml up -d --build",
        "match": "prod"
    }
]

调用命令时选择一个模板

如果从命令模板中省略 match 属性,则每次调用 compose up 命令时,系统都会询问您要使用哪个模板。例如

"docker.commands.composeUp": [
    {
        "label": "dev",
        "template": "docker-compose -f docker-compose.yml -f docker-compose.common.dev.yml ${configurationFile} up -d --build"
    },
    {
        "label": "test",
        "template": "docker-compose -f docker-compose.yml -f docker-compose.common.test.yml ${configurationFile} up -d --build"
    },
    {
        "label": "prod",
        "template": "docker-compose -f docker-compose.yml -f docker-compose.common.prod.yml ${configurationFile} up -d --build"
    },
],

自定义任务

您还可以定义如下任务来调用 docker-compose 命令,而不是使用命令自定义。有关此选项的更多详细信息,请参阅 自定义任务

{
  "type": "shell",
  "label": "compose-up-dev",
  "command": "docker-compose -f docker-compose.yml -f docker-compose.Common.yml -f docker-compose.dev.yml up -d --build",
  "presentation": {
    "reveal": "always",
    "panel": "new"
  }
}

后续步骤