首页 > 解决方案 > Docker 容器在 Visual Studio 中工作,但在使用命令行时不工作

问题描述

我想要完成的事情

我试图创建的最终结果是 Web API 不暴露给 localhost,但 Web MVC 网站可以与 Web API 通信,解析其结果的场景。

背景

我是 Docker 世界的新手,当我学会了如何并排运行多个容器时,现在我正在尝试使用两个容器之间的网络来回溯我迄今为止所学的一切。

我创建了两个简单的、开箱即用的 .NET 5.0 应用程序:

1. Web API(通过HTTP,端口访问7070

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 7070

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["CreatingWebAPI/CreatingWebAPI.csproj", "CreatingWebAPI/"]
RUN dotnet restore "CreatingWebAPI/CreatingWebAPI.csproj"
COPY . .
WORKDIR "/src/CreatingWebAPI"
RUN dotnet build "CreatingWebAPI.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "CreatingWebAPI.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_URLS http://+:7070
ENTRYPOINT ["dotnet", "CreatingWebAPI.dll"]
    "Docker": {
      "commandName": "Docker",
      "launchBrowser": true,
      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
      "publishAllPorts": true,
      "useSSL": true
    }
webBuilder.UseUrls("http://*:7070").UseStartup<Startup>();

2.显示来自 Web API 的解析表的 Web MVC

我目前面临的问题

通过 Visual Studio 运行 Web API 应用程序(使用Docker配置)工作得很好,我可以localhost:<port>/swagger毫无问题地访问。问题是,在尝试使用 Docker CLI 重现相同过程时 - 我无法访问/swagger接口,无论我尝试访问什么端口或端口。

附件是 docker CLI 的照片,显示了两个容器的相同细节: 容器

  1. 使用 Visual Studio 生成
  2. 使用生成docker run --network personal-net --name api -p 50000:7070 creatingwebapi

我使用了不同的网络,并尝试一次只创建一个。我什至尝试docker container inspect了这两种方法来检查它们之间的任何差异,而没有看到任何不同。那可能是什么问题?

标签: visual-studiodockerapinetworkingcontainers

解决方案


特别是关于您的问题:Swagger 公开您的端点输入、输出、模型,甚至允许任何人测试它们(“试用”按钮)。除了开发之外,您不希望在任何环境中出现这种情况。在过去,同样的事情也适用于 wcf 和元数据公开。

webapi 模板遵循这个基本原理,您可以在 startup.cs 文件中找到它:

       if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseSwagger();
            app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication2 v1"));
        }

"if (env.IsDevelopment())" 只允许在开发环境中使用 swagger,或者说:ASPNETCORE_ENVIRONMENT=Development。如果你不指定环境,那么它是空白的,它不是开发,所以 env.isdevelopment() 是假的,因此你不会大摇大摆。

我至少可以想到 3 个选项供您探索和了解正在发生的事情。这三个中的任何一个都应该让您大摇大摆,因为他们将环境设置为 DEVELOPMENT 或者他们删除了这个“唯一的开发”条件:

  1. 在 Dockerfile 文件中将环境设置为 DEVELOPMENT(请记住 x.development.json 的约定,例如 appsettings)。就像是: ENTRYPOINT ["dotnet", "WebApplication2.dll","--environment=Development"]
  2. 运行 docker 容器,将环境变量指定为 Development:docker run -e "ASPNETCORE_ENVIRONMENT=Development" -P --name WebApplication2 webapplication2
  3. 删除 startup.cs 文件中的 if 条件。

我个人反对第 3 项。Swagger 元数据在较低的环境中很有用(您甚至可以从中创建代理对象),但不应在生产环境中公开。

我认为这里有一个更大的图景:你不希望你的 API 暴露给外界。因此,根据您的定义,来自 docker 环境之外的任何人(甚至您)都不能访问 swagger。

我正在考虑如何拒绝外界对 api 的访问(希望在这里触发想法):

  1. 仍然保持招摇:使用防火墙拒绝传入流量到 weabpi 容器的 ip/port。
  2. 失去访问 API ip/port 的能力:尝试让容器相互通信,让容器(web 和 api)相互通信需要它们之间的内部连接,但不一定将 ipport 暴露给主机. https://www.tutorialworks.com/container-networking/

推荐阅读