When you try do dockerize ASP.NET Core application with Angular, you most probably faced with this error.
The command “npm install” exited with code 127.
So, why it happens ?
Because of publish stage happens on based microsoft/dotnet:2.1-sdk image. So, this dockerfile contains only dotnet sdk but not npm installed this base image.
What is the solution ?
We should use other image in our dockerfile too. In order to be able build our frontend.
I seperated npm side as different build stage on dockerfile. So, firstly you should remove npm commands on publish in *.csproj file. So, i removed all red lines entirely from my *.csproj file.
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp2.1</TargetFramework> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion> <IsPackable>false</IsPackable> <SpaRoot>ClientApp\</SpaRoot> <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes> <!-- Set this to true if you enable server-side prerendering --> <BuildServerSideRenderer>false</BuildServerSideRenderer> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <UserSecretsId>780680aa-e49b-4ae0-b3bc-868cb1e482aa</UserSecretsId> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" /> <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.1.1" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.0.2105168" /> </ItemGroup> <ItemGroup> <!-- Don't publish the SPA source files, but do show them in the project files list --> <Content Remove="$(SpaRoot)**" /> <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" /> </ItemGroup> <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') "> <!-- Ensure Node.js is installed --> <Exec Command="node --version" ContinueOnError="true"> <Output TaskParameter="ExitCode" PropertyName="ErrorCode" /> </Exec> <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." /> <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." /> <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" /> </Target> <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 -- --prod" /> <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " /> <!-- Include the newly-built files in the publish output --> <ItemGroup> <DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" /> <DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" /> <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)"> <RelativePath>%(DistFiles.Identity)</RelativePath> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> </ResolvedFileToPublish> </ItemGroup> </Target> </Project>
So, try to build docker file again, it should be build without any error.
docker build -t angularapp2 .
Yes, it was successfull. But on this way we builded dockerfile only with backend but not with frontend side. We should build and publish our frontend in dockerfile. So, my Dockerfile looks like this:
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM microsoft/dotnet:2.1-sdk AS build WORKDIR /src COPY ["angularApp2.csproj", "angularApp2/"] RUN dotnet restore "angularApp2/angularApp2.csproj" COPY . angularApp2/ WORKDIR "/src/angularApp2" RUN dotnet build "angularApp2.csproj" -c Release -o /app FROM build AS publish RUN dotnet publish "angularApp2.csproj" -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . ENTRYPOINT ["dotnet", "angularApp2.dll"]
I added frontend build stage to this file, after changes my code will look like below:
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM microsoft/dotnet:2.1-sdk AS build WORKDIR /src COPY ["angularApp2.csproj", "angularApp2/"] RUN dotnet restore "angularApp2/angularApp2.csproj" COPY . angularApp2/ WORKDIR "/src/angularApp2" RUN dotnet build "angularApp2.csproj" -c Release -o /app FROM build AS publish RUN dotnet publish "angularApp2.csproj" -c Release -o /app #Angular build FROM node as nodebuilder # set working directory RUN mkdir /usr/src/app WORKDIR /usr/src/app # add `/usr/src/app/node_modules/.bin` to $PATH ENV PATH /usr/src/app/node_modules/.bin:$PATH # install and cache app dependencies COPY ClientApp/package.json /usr/src/app/package.json RUN npm install RUN npm install -g @angular/cli@1.7.0 --unsafe # add app COPY ClientApp/. /usr/src/app RUN npm run build #End Angular build FROM base AS final WORKDIR /app COPY --from=publish /app . RUN mkdir -p /app/ClientApp/dist COPY --from=nodebuilder /usr/src/app/dist/. /app/ClientApp/dist/ ENTRYPOINT ["dotnet", "angularApp2.dll"]
And build you docker image again and run it.
docker build -t angularapp2 . docker run -p 80:80 -d angularapp2
yaay it works 😊
For some reason the `ng build` creates a folder named `ClientApp` in the dist folder.
So my last copy command looks like:
“`
COPY –from=nodebuilder /usr/src/app/dist/ClientApp/. /app/ClientApp/dist/
“`
Awesome .. thanks
Or Maybe Just add following commands to publish image (without change project file)
FROM build AS publish
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash –
RUN apt-get install -y nodejs
I keep getting a “unauthorized: authentication required”.
What would be causing that?
“ERROR: “/ClientApp” not found: not found” please help