Home > Software design >  .Net Core 3.1 Docker troubles
.Net Core 3.1 Docker troubles

Time:12-01

I'm new to docker and I'm trying to "dockerise" my .Net Core 3.1 web app and have been having lots of issues. I think I'm close with my current configuration, but I can't resolve the following error

#20 15.48   /bin/sh: 2: /tmp/tmp304aa1375f814c218c0b827fa8987b12.exec.cmd: npm: not found
#20 15.49 /src/AptivDataViz.UI/AptivDataViz.UI.csproj(193,5): error MSB3073: The command "npm install" exited with code 127.

Here's my DockerFile:

# https://medium.com/@oluwabukunmi.aluko/dockerize-asp-net-core-web-app-with-multiple-layers-projects-part1-2256aa1b0511
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE $PORT
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src

COPY myapp.UI/*.csproj ./myapp.UI/
COPY myapp.Data/*.csproj ./myapp.Data/
COPY myapp.DTO/*.csproj ./myapp.DTO/
COPY myapp.LiteDB/*.csproj ./myapp.LiteDB/
COPY myapp.Repository/*.csproj  ./myapp.Repository/

#RUN echo ''

RUN dotnet restore "myapp.UI/myapp.UI.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "myapp.UI/myapp.UI.csproj" -c Release -o /app/build

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

FROM base AS final
WORKDIR /app

COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "myapp.ui.dll"]

I also tried the following config, but got the same result:

FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 8080
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY *.sln .
COPY myapp.UI/*.csproj ./myapp.UI/
#RUN dotnet restore 

COPY . .
WORKDIR "/src/myapp.UI"
RUN dotnet build  -c Release -o /app/build



FROM build AS publish
RUN dotnet publish  -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "myapp.UI.dll"]

csproj:

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
     <!--As part of publishing, ensure the JS resources are freshly built in production mode--> 
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />

     <!--Include the newly-built files in the publish output--> 
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)build\**; $(SpaRoot)build-ssr\**" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
        <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>

npm install and npm run build from my Clientapp folder both execute wihtout any errors.

Following a recommendation of this page, I removed the Target nodes from the csproj and this resulted in a successful docker build, but it didn't run so I'm thinking that was not the right advice

docker-compose

version: '3.5'

services:
  aptivpoc:
    build:
      context: .
      dockerfile: Dockerfile
    image: myapp:dev
    container_name: myapp
    restart: unless-stopped
    env_file:
      - .env

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedMemoryCache();

    services.AddSession(options =>
    {
        options.IdleTimeout = System.TimeSpan.FromMinutes(30);
        options.Cookie.HttpOnly = true;
        options.Cookie.IsEssential = true;
    });

    services.AddControllersWithViews();
    services.AddHttpContextAccessor();

    // In production, the React files will be served from this directory
    services.AddSpaStaticFiles(configuration =>
    {
        configuration.RootPath = "ClientApp/build";
    });
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "Dashboard API", Description="Tool for testing dashboard API endpoints", Version = "v1" });
    });
}

I run the following command from the folder where my sln file is (one level above the project folder where the DockerFile is docker build -f myapp.UI\Dockerfile --force-rm -t myapp.ui .

I did manage to get a previous app to successfully build into a do

EDIT I am basing my DockerFile off of this: https://docs.docker.com/samples/dotnetcore/ and this: https://softchris.github.io/pages/dotnet-dockerize.html

CodePudding user response:

You need to install node and npm in the SDK image, since they aren't there in the standard image. You can install them by adding a line in the build step of your Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
# Add this line VVVVV
RUN apt-get update && apt-get install -y nodejs npm
WORKDIR /src

CodePudding user response:

I got it working! I took some inspiration from this post that suggested removing the entire Target section from the csproj file, but doing that also failed. Thanks to Obsidian Age's comment, I decided to try removing the npm commands from csproj. I just removed the following two elements from the csproj

<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />

Prior to that, I also whittled my DockerFile down to the following:

FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 8080
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY *.sln .
COPY myapp.UI/*.csproj ./myapp.UI/
#RUN dotnet restore 

COPY . .
WORKDIR "/src/myapp.UI"
RUN dotnet build  -c Release -o /app/build

FROM build AS publish
RUN dotnet publish  -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "myapp.UI.dll"]

docker build -f myapp.UI\Dockerfile --force-rm -t myapp.ui .

docker run -d -p 8080:80 --name containername myapp.ui

et voila! Site is running from Docker!

It's worth noting that I did not add those two elements to the csproj. I started the project in Visual Studio Enterprise 2019 using a React .Net Core 3.1 template and the csproj file was created that way. I'll have to see how publishing directly to Azure App Service (just for UAT) works (or fails!) now.

  • Related