Search code examples
c#asp.net.netdockerasp.net-core

minimal docker for ASP.NET Core


I can build a simple REST API endpoint with ASP.NET Core:

$ rm -rf PPP && mkdir PPP && cd PPP # <--- make sure dir is empty
$ dotnet new web 1>/dev/null
$ dotnet run
Building...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5270
# ... omitted other info ...

When I send an http GET request, everything works fine:

$ curl http://localhost:5270/
Hello World! # <--- good ! (the default response generate in `dotnet new web`)                                                                                                   

When I try to "dockerize" it according to this guide, it doesn't work:

# Dockerfile 
FROM mcr.microsoft.com/dotnet/sdk:8.0
RUN mkdir Properties
COPY Program.cs Program.cs
COPY PPP.csproj PPP.csproj
COPY appsettings.json appsettings.json
COPY appsettings.Development.json appsettings.Development.json
COPY Properties/launchSettings.json Properties/launchSettings.json
EXPOSE 5270
CMD ["dotnet", "run"]

Here is how I build and run the docker image

$ docker build --tag host --file Dockerfile .
$ docker run -p 8000:5270 -d -t --name scfrontcs host

And here is the error I get:

$ curl http://localhost:8000/                 
curl: (52) Empty reply from server

What am I doing wrong ?


EDIT

  • I had trouble running 8.0 on my macos, so I downgraded the image to 7.0
  • I can now send GET requests from within the docker
  • But not from outside (from my local machine)
$ cat Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:7.0
WORKDIR /App
COPY Program.cs Program.cs
COPY scfrontcs.csproj scfrontcs.csproj
COPY appsettings.json appsettings.json
EXPOSE 5000
# CMD ["dotnet", "run"] <--- commented, I will run it myself

$ docker build --tag host --file Dockerfile .
$ docker run -p 8000:5000 -d -t --name scfrontcs host
$ docker exec -it scfrontcs bash                     
root@fca567cab821:/App# dotnet run & # inside docker
[1] 97
root@fca567cab821:/App# info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
# ... omitted info ...
curl http://localhost:5000
Hello World # <--- works from within docker !

Solution

  • launchSettings.json is for development environments only:

    The launchSettings.json file:

    • Is only used on the local development machine.
    • Is not deployed.
    • Contains profile settings.

    And the provided article does not copy it to the docker image.

    If as PoC you want to fiddle with it in docker image then you need to set corresponding environment variable (DOTNET_ENVIRONMENT and/or ASPNETCORE_ENVIRONMENT depending on the framework version) to Development.

    But in general you should not do it, by default ASP.NET Core will listen on 80 (pre .NET 8) or 8080 (.NET 8) port in the container so just use and map to it - -p 8000:8080. If you want to use another port inside the container - set ASPNETCORE_URLS to wanted value or for .NET 8 - ASPNETCORE_HTTP_PORTS.

    Also add WORKDIR /App on the next line after FROM - for some reason dotnet command hangs in the root folder (or at least works too long) and wait a bit after starting the container.

    But in general it is recommended to follow the standard patterns for image building as one in the docs you have browse. It uses multistage build which allows to reduce the final container size since it will have only runtime without SDK.

    See also: