dotnet / dotnet-docker

Docker images for .NET and the .NET Tools.
https://hub.docker.com/_/microsoft-dotnet
MIT License
4.47k stars 1.94k forks source link

Unable to run ASP.NET Web API on jammy-chiseled docker image #5025

Closed Arclight3 closed 9 months ago

Arclight3 commented 11 months ago

Describe the Bug

I have a .net 7 Web API with this config:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UserSecretsId>MySecretGuid</UserSecretsId>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
    <NoWarn>$(NoWarn);1591</NoWarn>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.13" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
  </ItemGroup>
</Project>

I am using the latest version of Visual Studio (17.8.1) and Docker (4.25.2). I have the .net 7 (7.0.311) and .net 8 (8.0.100) SDKs installed (latest patches).

I have this Dockerfile:

# Build stage/image
FROM mcr.microsoft.com/dotnet/sdk:7.0-jammy AS build

WORKDIR /source
COPY ["nuget.config", "."]
COPY ["MyApp/MyApp.Api.csproj", "MyApp.Api/"]

ENV NUGET_XMLDOC_MODE none
RUN dotnet restore "MyApp.Api/MyApp.Api.csproj" --configfile nuget.config

COPY [".", "."]
WORKDIR "/source/MyApp.Api"
ARG buildnumber
RUN dotnet publish "MyApp.Api.csproj" --no-restore -c Release -p:Version=$buildnumber -o /app

# Final stage/image
FROM mcr.microsoft.com/dotnet/aspnet:7.0-jammy-chiseled as final
WORKDIR /app
COPY --from=build /app .

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

ENTRYPOINT ["./MyApp.Api"]

My launchSettings.json is:

{
  "profiles": {
    "Docker": {
      "commandName": "Docker",
      "launchBrowser": true,
      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "dev",
        "ASPNETCORE_URLS": "http://+:8080"
      },
      "publishAllPorts": true
    }
  },
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:51940",
      "sslPort": 0
    }
  }
}

Initially I was using the mcr.microsoft.com/dotnet/aspnet:7.0 base image and everything worked fine. After I update the Dockerfile to use the mcr.microsoft.com/dotnet/aspnet:7.0-jammy-chiseled image (or the 8.0-jammy-chiseled), I get this error in Visual Studio when I run the application in Docker:

vs_log_0.txt

I have read and followed the instructions from this page: https://github.com/dotnet/dotnet-docker/blob/main/documentation/ubuntu-chiseled.md and I think my Dockerfile looks ok. I think it's a support problem with Visual Studio or the Microsoft.VisualStudio.Azure.Containers.Tools.Targets NuGet package regarding the new jammy-chiseled Docker images.

Please let me know if I can provide more information.

Steps to Reproduce

Other Information

Output of docker version

docker_version_output.txt

Output of docker info

docker_info_output.txt

lbussell commented 11 months ago

[Triage] This looks like an issue with the Visual Studio container tooling/targets as you mentioned. Please file an issue on https://github.com/microsoft/dockertools/issues instead.

Arclight3 commented 10 months ago

This issue actually happens also when I try to build the image from the command line (from sln directory):

Command:

docker build -t manual-built-app:10.6.1.0 --progress=plain -f .\MyApp.Api\Dockerfile --build-arg buildnumber=10.6.1.0 .

Output:

2023/12/06 16:42:34 http2: server: error reading preface from client //./pipe/docker_engine: file has already been closed
#0 building with "default" instance using docker driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 922B done
#1 DONE 0.0s

#2 [internal] load .dockerignore
#2 transferring context: 382B done
#2 DONE 0.0s

#3 [internal] load metadata for mcr.microsoft.com/dotnet/aspnet:7.0-jammy-chiseled
#3 DONE 0.0s

#4 [internal] load metadata for mcr.microsoft.com/dotnet/sdk:7.0-jammy
#4 DONE 0.0s

#5 [base 1/2] FROM mcr.microsoft.com/dotnet/aspnet:7.0-jammy-chiseled
#5 DONE 0.0s

#6 [build 1/8] FROM mcr.microsoft.com/dotnet/sdk:7.0-jammy
#6 CACHED

#7 [base 2/2] WORKDIR /app
#7 CACHED

#8 [final 1/2] WORKDIR /app
#8 DONE 0.0s

#9 [build 2/8] WORKDIR /src
#9 DONE 0.0s

#10 [internal] load build context
#10 transferring context: 72.17MB 1.4s done
#10 CANCELED
ERROR: failed to solve: error from sender: context canceled

So it doesn't seem to be Visual Studio or tooling related. It's strictly related to the jammy-chiseled image.

@lbussell Please reopen this issue.

mthalman commented 10 months ago

@Arclight3 - You're getting a different error than the original post. Please log a new issue here.

Arclight3 commented 10 months ago

Alright but it's the same problem. First I presented the VS output, now the cli output. :)

mthalman commented 10 months ago

Ah, sorry about that. I didn't realize you were the OP.

Arclight3 commented 10 months ago

Ah, sorry about that. I didn't realize you were the OP.

No worries. Thanks for reopening it! 😄

lbussell commented 10 months ago

[Triage] Looking at your build error, error reading preface from client //./pipe/docker_engine: file has already been closed, this looks like a Docker issue unrelated to .NET. Given the errors start before you reach the final stage, it doesn't seem like this is related to using a jammy-chiseled image either. Can you rebuild your image using a different, non-chiseled tag (e.g. mcr.microsoft.com/dotnet/aspnet:7.0-jammy) and share the output?

Arclight3 commented 10 months ago
  1. I am not sure the first docker error is relevant. It doesn't appear all the time. I attached multiple CLI outputs. Hopefully it will help to decide if that error is relevant.

  2. I tried to build the Dockerfile with a few image combinations. I tried from both Visual Studio and CLI (docker build -t manual-built-app:10.6.1.0 --progress=plain -f .\MyApp.Api\Dockerfile --build-arg buildnumber=10.6.1.0 .). This is what I found:

WORKDIR /source COPY ["nuget.config", "."] COPY ["MyApp/MyApp.Api.csproj", "MyApp.Api/"]

ENV NUGET_XMLDOC_MODE none RUN dotnet restore "MyApp.Api/MyApp.Api.csproj" --configfile nuget.config

COPY [".", "."] WORKDIR "/source/MyApp.Api" ARG buildnumber RUN dotnet publish "MyApp.Api.csproj" --no-restore -c Release -p:Version=$buildnumber -o /app

Final stage/image

FROM mcr.microsoft.com/dotnet/aspnet:7.0 as final

FROM mcr.microsoft.com/dotnet/aspnet:7.0-jammy as final

FROM mcr.microsoft.com/dotnet/aspnet:7.0-jammy-chiseled as final

WORKDIR /app COPY --from=build /app .

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

ENTRYPOINT ["./MyApp.Api"]

All combinations of images presented in the Dockerfile above fail with these errors:
[vs_log_1.txt](https://github.com/dotnet/dotnet-docker/files/13612780/vs_log_1.txt)
[cli_log_1.txt](https://github.com/dotnet/dotnet-docker/files/13612785/cli_log_1.txt)

- Building the docker layers in this order (base -> build -> final) with the following images works from VS (but still fails on CLI). The commented FROM statements shows what other combinations I tried (4 total):
```Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
#FROM mcr.microsoft.com/dotnet/aspnet:7.0-jammy AS base
WORKDIR /app
EXPOSE 8080
ENV ASPNETCORE_URLS=http://*:8080

# Build stage/image
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
#FROM mcr.microsoft.com/dotnet/sdk:7.0-jammy AS build

WORKDIR /source
COPY ["nuget.config", "."]
COPY ["MyApp.Api/MyApp.Api.csproj", "MyApp.Api/"]

ENV NUGET_XMLDOC_MODE none
RUN dotnet restore "MyApp.Api/MyApp.Api.csproj" --configfile nuget.config

COPY [".", "."]
WORKDIR "/source/MyApp.Api"
ARG buildnumber
RUN dotnet publish "MyApp.Api.csproj" --no-restore -c Release -p:Version=$buildnumber -o /app

# Final stage/image
FROM base AS final
WORKDIR /app
COPY --from=build /app .

ENTRYPOINT ["./MyApp.Api"]

vs_log_2.txt cli_log_2.txt

Build stage/image

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build

FROM mcr.microsoft.com/dotnet/sdk:7.0-jammy AS build

WORKDIR /source COPY ["nuget.config", "."] COPY ["MyApp.Api/MyApp.Api.csproj", "MyApp.Api/"]

ENV NUGET_XMLDOC_MODE none RUN dotnet restore "MyApp.Api/MyApp.Api.csproj" --configfile nuget.config

COPY [".", "."] WORKDIR "/source/MyApp.Api" ARG buildnumber RUN dotnet publish "MyApp.Api.csproj" --no-restore -c Release -p:Version=$buildnumber -o /app

Final stage/image

FROM base AS final WORKDIR /app COPY --from=build /app .

ENTRYPOINT ["./MyApp.Api"]


[vs_log_3.txt](https://github.com/dotnet/dotnet-docker/files/13612879/vs_log_3.txt)
[cli_log_3.txt](https://github.com/dotnet/dotnet-docker/files/13612913/cli_log_3.txt)

**Conclusions**:
- The CLI build **fails** always
- The VS build **fails** always with layers order (build -> final)
- The VS build **works** with layers order (base -> build -> final) - when not using jammy-chiseled
- The VS build **fails** with layers order (base -> build -> final) - when using jammy-chiseled
lbussell commented 10 months ago

[Triage] We haven't forgotten about this issue - we'd like to continue investigation after the new year.

Arclight3 commented 9 months ago

Hi. Any updates? :)

lbussell commented 9 months ago

I took a look at this today. Here's what I did:

Then I was able to build the Dockerfile with the command docker build -t test --progress=plain --build-arg buildnumber=1.0.0 .. Both Jammy and Jammy Chiseled worked here. Running the app via Docker CLI I was able to access the API from the browser. Here's my cli output if you want to compare to yours - cli_log.txt

Then I tried running via Docker in Visual Studio. Using jammy-chiseled didn't work because Visual Studio (or the Microsoft.VisualStudio.Azure.Containers.Tools.Targets package) tries to run tail in the image that got built, which fails since there's no shell or tail executable in the distroless image. This probably needs an issue opened against that project. Reverting to distro-full Jammy, the Dockerfile builds and runs, but Visual Studio seems to ignore the ports in the Dockerfile and in launchSettings.json. Not sure what's going on there, I'd have to investigate more, but the Dockerfile does build and run (while it doesn't on your machine). I'm unable to reproduce your specific issue.

I still think that your CLI output looks like a problem with your Docker installation. I have a few suggestions for you -

  1. Try with the new .NET servicing release that was released this week (pull all of your images before building again)
  2. Un-install and re-install Docker Desktop
  3. Try publishing directly to a container from the .NET SDK - this approach sidesteps the Docker build process altogether and outputs an OCI-compliant container directly from the dotnet publish command. You can specify your desired base image in your project file. https://learn.microsoft.com/en-us/dotnet/core/docker/publish-as-container?pivots=dotnet-7-0
richlander commented 9 months ago

We came to the conclusion that adding tail to chiseled images to make Visual Studio tools work was counter-productive. For folks that want to use the tools, they should use regular Ubuntu for the tools and then chiseled for prod.

lbussell commented 9 months ago

[Triage] Converting this to a discussion because there isn't any obvious work to be done here but we're interested in continuing the conversation.