如何在 VS Code devcontainer 中运行 docker-compose

21

我有一个多容器项目,由3个NestJS和1个dotnet5.0应用程序组成。除了这些应用程序之外,该项目还依赖于RabbitMQ和InfluxDB服务(作为纯Docker镜像运行)

docker-compose文件如下所示:

version: '3.8'

services:
  influxdb:
    image: influxdb:2.0
    container_name: influxdb
    ports:
      - '8086:8086'
    expose:
      - '8086'
    volumes:
      - ./data/influxdb2/data:/var/lib/influxdb2
      - ./data/influxdb2/config:/etc/influxdb2

  rabbitmq:
    hostname: 'rabbitmq'
    image: rabbitmq:3-management
    container_name: rabbitmq
    ports:
      - '15672:15672'
      - '5672:5672'

  microservice1:
    image: microservice1
    container_name: microservice1
    depends_on: [rabbitmq, influxdb]
    build:
      context: .
      dockerfile: ./apps/microservice1/Dockerfile

  microservice2:
    image: microservice2
    container_name: microservice2
    depends_on: [rabbitmq, influxdb]
    build:
      context: .
      dockerfile: ./apps/microservice2/Dockerfile

  microservice3:
    image: microservice3
    container_name: microservice3
    depends_on: [rabbitmq, influxdb]
    build:
      context: .
      dockerfile: ./apps/microservice3/Dockerfile

  microservice4:
    image: microservice4
    container_name: microservice4
    depends_on: [rabbitmq, influxdb]
    build:
      context: .
      dockerfile: ./apps/microservice4/Dockerfile

我希望将整个开发环境迁移到新的VS Code devcontainers,但我不太清楚如何处理依赖项(比如这里的rabbitmq和influxdb)。

理想情况下,我会在一个同时包含nodejs和dotnet SDK的devcontainer中打开仓库,以便在开发过程中运行微服务。但是,我不想在devcontainer中安装influxdb和rabbitmq,因为我想利用现有的(方便的)docker镜像。

问题是,一旦我在devcontainer内部打开了仓库,就无法从内部与docker-compose交互(因为docker/docker-compose在devcontainer内不可用)。

是否可能从容器内部与主机上的Docker引擎进行交互?这样我就可以简单地拥有一个dev.sh脚本,可以简单地启动rabbitmq和influxdb依赖项,然后启动我想要运行的任何微服务吗?

也许我弄错了,但我找不到一个清晰的解释,说明如何混合使用VS Code devcontainers和基于镜像的docker-compose文件。

3个回答

19

vscode只能使用一个服务作为“工作区”,在该IDE运行时。就像在本地工作时,您在IDE上工作,其他服务在其他容器中运行。

您当前的任何服务都不适合作为IDE工作区,“好的”选项是添加一个服务。这将像您的主机机器一样,但在容器中。

您可以使用多个组合文件,以便在不更改当前docker-compose.yml的情况下添加新服务。

因此,第一部分:

  1. 创建第二个docker-compose.yml文件(可能是:docker-compose.workspace.yml
  2. 在该文件中添加一个单独的服务,可能称为“workspace”。 vscode远程部分将在那里运行。什么镜像?您可以使用一个vscode预先制作的镜像
  3. .devcontainer.json中指向两个文件并定义工作区服务:
...
  "dockerComposeFile": [
    "docker-compose.yaml",
    "docker-compose.workspace.yaml"
  ],
  "service": "workspace",
...

好的。这为您提供了工作区容器和侧边栏上的所有其他内容。这将带我们到问题的另一部分:

在容器内是否可以与主机上的Docker引擎交互?这样我就可以简单地编写一个dev.sh脚本,以便可以启动rabbitmq和influxdb依赖项,然后启动任何想要运行的微服务?

首先,如果您想要使用docker和docker-compose命令,您必须安装这些软件包。有些镜像中已经内置了它们,而有些则没有。您可以使用自己的镜像等。

但这还不够。您的工作区容器不知道主机的docker。但是很容易解决。只需添加卷挂载即可:

/var/run/docker.sock:/var/run/docker.sock

通过工作区服务。这样vscode将“看到”您的主机上的docker并与之交互。

请注意,这仍然是主机的docker,因此根据您所做的内容可能会在路径等方面遇到问题。


2
这有道理。谢谢! - empz

4

我最近开始自己摸索,并分享一下我的经验。我还在调整权限,但以root身份运行时一切正常。据我所知,你不需要更改工作中的docker-compose.yml文件。我的文件看起来像这样:

version: '3.9'

services:
    app:
        build:
            context: ./
            dockerfile: Dockerfile
        command: sleep infinity
        user: root
        ports:
            - 5001:5001
            - [snip]
        depends_on:
            - mysql
    mysql:
        image: mysql:8
        ports:
            - 3306:3306
        restart: unless-stopped
        environment:
            MYSQL_ROOT_PASSWORD: myRootpwd32

以下内容来自VS Code生成的标准Dockerfile(为了简洁已截断):

# [Choice] .NET version: 5.0, 3.1, 2.1
ARG VARIANT="3.1"
FROM mcr.microsoft.com/vscode/devcontainers/dotnet:0-${VARIANT}

# [Option] Install Node.js
ARG INSTALL_NODE="true"
ARG NODE_VERSION="lts/*"
RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

最后是 devcontainer.json 文件:

{
    "name": "C# (.NET)",
    "dockerComposeFile": "docker-compose.yml",
    "service": "app",
    "workspaceFolder": "/workspaces/MemberCore",

    // Set *default* container specific settings.json values on container create.
    "settings": {
        "terminal.integrated.shell.linux": "/bin/bash"
    },

    // Add the IDs of extensions you want installed when the container is created.
    "extensions": [
        "ms-dotnettools.csharp",
        "wakatime.vscode-wakatime",
        "fernandoescolar.vscode-solution-explorer",
        "adrianwilczynski.add-reference",
        "kreativ-software.csharpextensions",
        "k--kato.docomment",
        "pranaygp.vscode-css-peek",
        "dbaeumer.vscode-eslint",
        "patcx.vscode-nuget-gallery",
        "derivitec-ltd.vscode-dotnet-adapter"
    ],
}

显然,关键在于 dockerComposeFile 这一行,它允许您重复使用您已经编写的内容。
我获取了很多信息来自这个仓库:https://github.com/0916dhkim/vscode-devcontainer-tutorial,其中提供了一个完整的从头开始的工作示例。

是的,但那只是在dev容器内运行docker-compose中声明的docker容器(实际上利用了主机的docker引擎)。这并没有增加任何额外的好处。我的意思是,我可以直接从我的机器上运行docker-compose而不必启动一个dev容器。我想在开发中运行我的微服务而不使用Docker(也就是说,我需要安装节点SDK、Python、dotnet等)。Docker compose只会用于启动数据库、代理和类似的依赖项。 - empz
我想我明白了。你实际上想让 devcontainer 拥有自己的 Docker 实例,并在“容器内部”启动容器? - Jesse Q
不,我只想利用主机的Docker引擎来启动容器(例如数据库、代理等依赖项),同时在devcontainer中运行实际的微服务(无需Docker)。 - empz
然后我仍然认为我们走在正确的轨道上。使用 docker-compose.yml 启动基于容器的依赖项(Rabbit、db),并且类似于我的示例中的 "app" 服务,使用 Dockerfile 构建您的微服务的 devcontainer,其中包括您的开发工具,如 node、npm 等。 - Jesse Q

2

您需要将Docker作为一个特性添加到devcontainer.json中:

"features": { "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {} }

这将允许访问主机上的docker套接字。

工作示例:devcontainer.json


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接