host.docker.internal在docker-compose中无法解析。

5

所以我有一个包含两个项目的.NET解决方案。当使用dotnet run运行时,它们工作正常,但是我在docker compose中遇到了问题。当添加用于容器之间通信的URL路径的环境变量时,我通常使用host.docker.internal来解析到其他容器的路径,但由于某种原因,它无法解析,并且只被用作例如https://host.docker.internal:49833/connect/authorize而不是https://localhost:49833/connect/authorize

对我来说这没有意义,因为我在我的机器上还有另一个项目,它使用这个设置完全正常。我错过了什么?

项目1的Dockerfile如下:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY ["RecipeManagement/src/RecipeManagement/RecipeManagement.csproj", "./RecipeManagement/src/RecipeManagement/"]
#COPY ["SharedKernel/SharedKernel.csproj", "./SharedKernel/"]
RUN dotnet restore "./RecipeManagement/src/RecipeManagement/RecipeManagement.csproj"

# Copy everything else and build
COPY . ./
RUN dotnet build "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj" -c Release -o /app/build

FROM build-env AS publish
RUN dotnet publish "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj" -c Release -o /app/out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=publish /app/out .

ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080

ENTRYPOINT ["dotnet", "/app/RecipeManagement.dll"]

项目2有一个Dockerfile,如下:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app

RUN curl -sL https://deb.nodesource.com/setup_16.x | bash -
RUN apt install -y nodejs

# Copy csproj and restore as distinct layers
COPY ["AuthServerWithDomain/AuthServerWithDomain.csproj", "./AuthServerWithDomain/"]
#COPY ["SharedKernel/SharedKernel.csproj", "./SharedKernel/"]
RUN dotnet restore "./AuthServerWithDomain/AuthServerWithDomain.csproj"

# Copy everything else and build
COPY . ./
RUN dotnet build "AuthServerWithDomain/AuthServerWithDomain.csproj" -c Release -o /app/build

FROM build-env AS publish
RUN dotnet publish "AuthServerWithDomain/AuthServerWithDomain.csproj" -c Release -o /app/out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=publish /app/out .

ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080

ENTRYPOINT ["dotnet", "/app/AuthServerWithDomain.dll"]

而且组合看起来像这样:

version: '3.7'

services:
  recipemanagement-db:
    image: postgres
    restart: always
    ports:
      - '63230:5432'
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: dev_recipemanagement
    volumes:
      - recipemanagement-data:/var/lib/postgresql/data

  recipemanagement-api:
    build:
      context: .
      dockerfile: RecipeManagement/src/RecipeManagement/Dockerfile
    ports:
      - "63231:8080"
    environment:
      ASPNETCORE_ENVIRONMENT: "Development"
      ASPNETCORE_URLS: https://+:8080;
      ASPNETCORE_Kestrel__Certificates__Default__Path: "/https/aspnetappcert.pfx"
      ASPNETCORE_Kestrel__Certificates__Default__Password: "password"
      DB_CONNECTION_STRING: "Host=recipemanagement-db;Port=5432;Database=dev_recipemanagement;Username=postgres;Password=postgres"
      "AUTH_AUDIENCE": "recipe_management"
      "AUTH_AUTHORITY": "https://host.docker.internal:49833"
#      ^^^^^^^^^^^ not sure why this and the below don't resolve *************************************************************************
      "AUTH_AUTHORIZATION_URL": "https://host.docker.internal:49833/connect/authorize"
      "AUTH_TOKEN_URL": "https://host.docker.internal:49833/connect/token"
      "AUTH_CLIENT_ID": "recipe_management.swagger"
      "AUTH_CLIENT_SECRET": "974d6f71-d41b-4601-9a7a-a33081f80687"
      "RMQ_HOST": "localhost:TBDRMQPORT"
      "RMQ_VIRTUAL_HOST": "/"
      "RMQ_USERNAME": "guest"
      "RMQ_PASSWORD": "guest"

    volumes:
      - ~/.aspnet/https:/https:ro
      
  recipemanagement-authserver:
    build:
      context: .
      dockerfile: AuthServerWithDomain/Dockerfile
    ports:
      - "49833:8080"
    environment:
      "ASPNETCORE_ENVIRONMENT": "Development"
      ASPNETCORE_URLS: "https://+:8080;"
      ASPNETCORE_Kestrel__Certificates__Default__Path: "/https/aspnetappcert.pfx"
      ASPNETCORE_Kestrel__Certificates__Default__Password: "password"

    volumes:
      - ~/.aspnet/https:/https:ro
        
volumes:
  recipemanagement-data:


相关:从Docker容器内部,如何连接到主机的本地地址? 在我的docker-compose.yml中添加extra_hosts:对我有帮助。 - Melebius
1个回答

3
请参考 @DavidMaze 的评论。最好从Compose 中的网络开始搜索。
(Dockerfile 对您的问题应该是无关紧要的。)有几个选项,需要尝试和错误来获得您想要的确切行为。我鼓励您在以下建议中寻找更好的解释:
在您的 compose 文件中,在 'service' 级别,您可以添加extra_hosts
my-service:
  extra_hosts:
    host.docker.internal:host-gateway
    #host.docker.internal:127.0.0.1 for linux

但是,当使用compose时,更好的选择是让Docker为您的容器创建一个特定于网络的网络,方法是使用docker network create --driver bridge my_recipe_ntwk

然后,在您的compose的顶层:

services:
volumes:
networks:
  my-private-ntwk:
    external:
      name: my_recipe_ntwk

并且在“服务”层面上。
my-service-1:
  networks:
    - my-private-ntwk

my-service-2:
  networks:
    - my-private-ntwk

对于在主机上运行的Postgres,请参见此答案,还应该有其他几个类似的答案。
我认为如果所有服务都配置在同一个桥接网络上,实际上您会使用服务名称,例如my-service-1:8080,并且不包括https。我可能是错误的。(在我的情况下,我的容器连接到主机上的Postgres,这需要'extra_hosts'和它自己的特殊解决方法。)您正在托管一个Postgres容器,因此我相信在使用桥接网络时,您的连接主机和端口将简单地是my-private-ntwk:5432

有趣,我会试一下。我该如何设置环境变量链接以使用这个网络?只需放置类似于 https://my_recipe_ntwk:5432 的内容即可吗? - Paul DeVito
我认为,如果所有的服务都配置在同一个桥接网络上,你实际上应该使用服务名称,例如 my-service-1:8080,而不包括 https。话虽如此,我并没有详细阅读你的 compose 文件。Postgres 是一个独特的存在。我将为 Postgres 编辑我的答案。 - mdisibio
1
Compose 会自动为您创建一个名为 default 的网络;您不需要运行 docker network create 或添加 networks: 块。实际上,您应该能够通过像 https://recipemanagement-authserver:8080 这样的 URL 从一个容器调用另一个容器(但要注意 TLS 证书名称需要与 URL 主机名匹配的问题)。Docker 文档中的 Compose 中的网络 对此有更多详细信息。 - David Maze
是的,我也尝试过这个。你可以看到我实际上正在使用我的数据库(它按预期工作),但是URL无法解析认证环境变量。 - Paul DeVito
@DavidMaze 这是一个关于默认网络文档的好链接。简单就是美。我的容器对容器和容器对主机的配置充满了五年来的SO黑科技和解决方案。 - mdisibio

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