Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker container works in Visual Studio, but does not when using command line

What I am trying to accomplish

The final result I'm trying to create is a scenario in which the Web API is not exposed to the localhost, yet the Web MVC website can communicate with the Web API, parsing its results.

Background

I'm new to the Docker world, and as I learned how to run multi containers side-by-side, now I'm trying to back-track everything I have learned so far using networking between two of the containers.

I have created two simple, out-of-the-box .NET 5.0 applications:

1. Web API (reaching through HTTP, using port 7070)

  • Dockerfile:
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"]
  • launchSettings.json:
    "Docker": {
      "commandName": "Docker",
      "launchBrowser": true,
      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
      "publishAllPorts": true,
      "useSSL": true
    }
  • Also defined Program.cs CreateHostBuilder(string[] args) as follow:
webBuilder.UseUrls("http://*:7070").UseStartup<Startup>();

2. Web MVC that shows a parsed table from the Web API

The issue I'm currently facing

Running the Web API application through Visual Studio (using Docker configuration) works just fine, and I can access the localhost:<port>/swagger without an issue. The problem is that while trying to reproduce the same process using the Docker CLI - I cannot access the /swagger interface matter what or what port I'm trying to access.

Attached is a photo of the docker CLI showing the same details about both of the containers: containers

  1. Generated using Visual Studio
  2. Generated using docker run --network personal-net --name api -p 50000:7070 creatingwebapi

I have used different networks and tried to create only one of them at a time. I even tried docker container inspect on both of these to check for any differences between them without seeing anything different. What might be the issue then?

like image 400
Erelephant Avatar asked Sep 02 '25 17:09

Erelephant


1 Answers

Specifically about your issue: Swagger exposes your endpoints inputs, outputs, models and even allows anyone to test them ("try it out" button). You don't want that in any environment other than DEVELOPMENT. Same thing applied to wcf and metadata exposure back in the days.

The webapi template follows this rationale and you can find it in the startup.cs file:

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

The "if (env.IsDevelopment())" allows usage of swagger only in development environment, or let's say: ASPNETCORE_ENVIRONMENT=Development. If you dont specify the environment, then it's blank, it's not Development, so env.isdevelopment() is false hence you don't get swagger.

I can think of 3 options at least for you to explore and to understand what's going on. Any of these 3 should give you swagger as they set the environment to DEVELOPMENT or they remove this "only development" condition:

  1. Set the environment as DEVELOPMENT (keep in mind the convention for the x.development.json such as appsettings) in the Dockerfile file. Something like: ENTRYPOINT ["dotnet", "WebApplication2.dll","--environment=Development"]
  2. Run the docker container specifying the environment variable as Development: docker run -e "ASPNETCORE_ENVIRONMENT=Development" -P --name WebApplication2 webapplication2
  3. Remove the if condition in startup.cs file.

I personally would be against item 3. Swagger metadata is useful in lower environments (where you can even create proxy objects out of it), but should not be exposed in Production.

I think there's a bigger picture here: you don't want your API to be exposed to the outside world. So by your definition, swagger should not be accesible by anyone from outside the docker environment (not even you).

I'm thinking how access to the api can be denied from the outside world (hopefully triggering ideas here):

  1. still keeping swagger: use a firewall to deny incoming traffic to the ip/port of the weabpi container.
  2. lose ability to reach the API ip/port: try to make the containers talk to each other, with the idea that making the containers (web and api) communicate to each other requires internal connectivity among them but not necessarily exposing an ipport to the host. https://www.tutorialworks.com/container-networking/
like image 198
Adrián Poplavsky Avatar answered Sep 04 '25 09:09

Adrián Poplavsky