使用 Docker Compose

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

此外,对于单容器场景,使用 Docker Compose 提供了工具无关的配置,而单个 Dockerfile 则无法做到。配置设置如容器的卷挂载、端口映射和环境变量,可以在docker-compose YML文件中声明。

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

为您的项目添加 Docker Compose 支持

如果你已经有一个或多个 Dockerfile,可以通过打开命令面板Windows,Linux Ctrl+Shift+P)并使用“容器:将 Docker Compose 文件添加到工作区”命令来添加 Docker Compose 文件。按照提示作。

你可以在添加 Docker 文件的同时,打开命令面板Windows,Linux 的 Ctrl+Shift+P并使用容器:将 Docker 文件添加到工作区的命令,同时添加 Docker Compose 文件到工作区。系统会问你是否想添加 Docker Compose 文件。如果你想保留现有的 Dockerfile,当被提示覆盖 Dockerfile 时选择“否”。

Container Tools 扩展增加了docker-compose.yml文件存档到你的工作区。该文件包含配置,使容器按生产环境正常运行。在某些情况下,adocker-compose.debug.yml也被生成。该文件提供了一个简化的启动模式,使调试器得以启用。

带有docker-compose文件的项目截图

VS Code 容器工具扩展生成的开箱即用文件,但你也可以自定义以优化你的场景。然后你可以使用Containers: Compose Up命令(右键点击docker-compose.yml文件,或者在命令调色板中找到命令)来一次性启动所有设备。你也可以使用docker-compose up在 VS Code 的命令提示符或终端窗口中执行命令,启动容器。请参阅 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,.dockerignore,docker-compose*.yml文件都放在工作区的根文件夹里。添加另一个应用或服务时,将 Dockerfile 移到应用文件夹中。

在Node.js项目中,Dockerfile以及.dockerignore文件会放在package.json为那项服务。

对于 .NET 来说,创建 Docker Compose 文件时,文件夹结构已经设置为可以处理多个项目,.dockerignore以及docker-compose*.yml放置在工作区根中(例如,如果项目在SRC/项目1,那么文件就在SRC),所以当你添加另一个服务时,你会在一个文件夹里创建另一个项目,比如说项目2,并按照之前描述的重建或修改docker-compose文件。

调试

首先,参考你目标平台的调试文档,了解使用 VS Code 在容器中调试的基础知识:

如果你想在 Docker Compose 中调试,可以使用前一节描述的两个 Docker Compose 文件中的一个执行命令 Containers: Compose Up,然后使用相应的 Attach 启动配置附加。直接使用正常启动配置启动时,不使用 Docker Compose。

创建一个“挂钩”发射配置。这是launch.json.这个过程大多是手动完成的,但在某些情况下,容器工具扩展可以通过添加预配置的启动配置来帮助你,你可以作为模板使用并进行自定义。每个平台(Node.js、Python 和 .NET)的流程将在以下章节中描述。

Node.js

  1. 调试标签中,选择配置下拉菜单,选择新配置,然后选择容器:附上配置模板容器:附加到节点

  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": "Containers: Attach to Node",
             "remoteRoot": "/usr/src/app",
             "port": 9229 // Optional; otherwise inferred from the docker-compose.debug.yml.
         },
         // ...
     ]
    
  4. 完成附件配置编辑后,保存launch.json,并选择你的新启动配置作为激活配置。在调试标签中,在配置下拉菜单中找到新配置。

    配置下拉菜单截图

  5. 右键点击docker-compose.debug.yml归档并选择“Compose Up”。

  6. 当你连接到一个暴露返回HTML的HTTP端点的服务时,网页浏览器不会自动打开。要在浏览器中打开应用,请在侧边栏选择容器,右键点击并选择“在浏览器中打开”。如果配置了多个端口,系统会要求你选择端口。

  7. 按常规方式启动调试器。在调试标签页中,选择绿色箭头(开始按钮)或按F5

Python

使用 Docker Compose 调试 Python 时,请遵循以下步骤:

  1. 调试标签页中,选择配置下拉菜单,选择新配置,选择 Python 调试器,然后选择远程连接配置模板。

    Python 远程连接截图

  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. 完成Attach配置编辑后,保存launch.json.进入“调试”标签,选择“Python Debugger: Remote Attach”作为激活配置。

  4. 如果您已经有有效的 Dockerfile,我们建议运行命令 Containers: Add Docker Compose Files to Workspace。这将产生docker-compose.yml文件,以及docker-compose.debug.yml,该卷映射并启动容器中的Python调试器。如果您还没有 Dockerfile,建议运行“容器:向工作区添加 Docker 文件”,并选择“是”以包含 Docker Compose 文件。

    注意:默认情况下,使用容器:添加到工作区文件时,选择Django和Flask选项会为Gunicorn配置的Dockerfile作为支架。按照容器中的 Python 快速启动说明作,确保配置正确后再继续。

  5. 右键点击docker-compose.debug.yml文件(示例如下所示)并选择“合成”

    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调试器:远程连接启动配置,连接调试器。

    用 Python 调试的截图

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

  7. 当你附加到一个暴露HTTP端点并返回HTML的服务时,网页浏览器可能不会自动打开。要在浏览器中打开应用,请在容器资源管理器中右键点击容器,然后选择“在浏览器中打开”。如果配置了多个端口,系统会要求你选择端口。

    截图 - 在浏览器中打开

    你现在是在容器里调试正在运行的应用。

.NET

  1. 调试标签中,选择配置下拉菜单,选择新配置,然后选择容器附着配置模板容器:.NET 附件(预览)。

  2. VS Code 尝试复制VSDBG从主机到目标容器,使用默认路径。你也可以提供通往现有实例的路径VSDBG附加配置中。

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

  4. 右键点击docker-compose.debug.yml归档并选择“Compose Up”。

  5. 当你连接到一个暴露返回HTML的HTTP端点的服务时,网页浏览器不会自动打开。要在浏览器中打开应用,请在侧边栏选择容器,右键点击并选择“在浏览器中打开”。如果配置了多个端口,系统会要求你选择端口。

  6. 按常规方式启动调试器。在调试标签页中,选择绿色箭头(开始按钮)或按F5

    开始调试的截图

  7. 如果你尝试连接到运行在容器中的 .NET 应用,你会看到一个提示,要求选择你的应用容器。

    容器选择截图

    要跳过这一步,请在launch.json的附件配置中指定容器名称:

        "containerName": "Your ContainerName"
    

    接着,你会被问是否想复制调试器(VSDBG)进入容器。选择“是”。

    调试器提示截图

如果配置正确,调试器应该会连接到你的 .NET 应用。

调试会话截图

音量安装

默认情况下,Container Tools 扩展不支持调试组件的卷挂载。在 .NET 或 Node.js 中不需要,因为所需的组件已经内置在运行时里。如果你的应用需要卷挂载,可以通过以下方式来指定卷数标签在docker-compose*.yml文件。

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

Docker Compose 搭配多个 Compose 文件

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

注意:如果你的工作区有docker-compose.yml以及docker-compose.override.yml没有其他 compose 文件,然后docker-compose命令调用时没有输入文件,并且隐式使用这些文件。在这种情况下,无需任何定制。

命令定制

命令自定义提供了多种方式来定制组装根据你的要求指挥。以下是一些示例命令自定义方法,组装指挥部。

基础文件和覆盖文件

假设你的工作区有一个基础的 compose 文件(docker-compose.yml)以及每个环境的覆盖文件(docker-compose.dev.yml,docker-compose.test.yml以及docker-compose.prod.yml)你总是在奔跑Docker Compose Up包含基础文件和覆盖文件。在这种情况下,组装命令可以像以下示例那样自定义。当组装命令被调用,${configurationFile}被选中的文件取代。

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

模板匹配

假设你为每个环境有一套不同的输入文件。你可以定义多个模板,正则表达式匹配,所选文件名会与此匹配比赛将使用属性和相应的模板。

"containers.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"
    }
]

调用命令时选择模板

如果你省略比赛命令模板中的属性,每次都会问你要用哪个模板组装命令被调用。例如:

"containers.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"
  }
}

下一步