NOTE: there are several questions about this topic already, which I reference below. While this question is in that sense a duplicate, I have tried to follow the advice in those other questions without success. Sometimes that's because the answer now refers to an out-of-date version of the relevant packages, and sometimes because it's not clear exactly how to implement the changes.
This question is my attempt to document a minimal, (non-)working example, with full instructions of how to reproduce the issue. Hopefully I can update it with similarly clear instructions on how to fix it.
I have the following environment:
- Windows 10 (enterprise, 1709)
- VS2017 (15.8.4)
- Node (11.5)
- Angular CLI (7.1.4)
- Docker Desktop (community, 2.0.0.2)
Here are the exact steps I followed to create an Angular SPA project:
Create a directory for the project
md MyAngularWebsite
cd MyAngularWebsite
Create the project using the
dotnet
CLI (using the Angular template)
dotnet new angular
If I open this solution in VS, I see all the files I'd expect to see:
...and if I run it (in IIS Express) it works as expected:
So far, so good.
Add Docker support
[Note: although I created the project via the .NET CLI, it's also possible to create projects using the Visual Studio UI. When doing this, there's an "Add Docker Support" checkbox in the new-project dialog. However, that checkbox is disabled for Angular projects. Presumably this is because it doesn't work. We can however get halfway there using the following method.]
I right-clicked on the website project (MyAngularWebsite
), and chose "Add Docker Support" from the pop-up menu.
Visual Studio asks for the type of Operating System that the Docker image will use - I chose Linux:
This seems to do two things:
- Adds a file named
Dockerfile
to the project. - Adds a new profile named "Docker" to
Properties\launchSettings.json
Here's the contents of Dockerfile
:
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 14242
EXPOSE 44321
FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY ["MyAngularWebsite.csproj", ""]
RUN dotnet restore "/MyAngularWebsite.csproj"
COPY . .
WORKDIR "/src/"
RUN dotnet build "MyAngularWebsite.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "MyAngularWebsite.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "MyAngularWebsite.dll"]
Now, if I start the project using the new "Docker" launch profile, there's a long pause while it downloads and builds all the required parts, and then a docker container is created, and a browser window is launched pointing to https://localhost:44321/
.
It's at this point that we see an error saying Failed to start 'npm'
:
Having read many other questions about this, I gather that the issue is simply that the base image (in this case microsoft/dotnet:2.2-aspnetcore-runtime
as specified at the top of the Dockerfile
) does not include Node.
Node is required so that the Angular app can be built, since ng build
is what's used to build it - and that relies on Node. (Although I have Node on my local machine, it's not on the Docker image on which the app is being built).
So, the suggested approach is to add Node to the Docker image by modifying the Dockerfile
.
Add Node to the Docker image
As suggested in the questions referenced above, I modified the Dockerfile
to include the following:
RUN apt-get update && \
apt-get install -y wget && \
apt-get install -y gnupg2 && \
wget -qO- https://deb.nodesource.com/setup_6.x | bash - && \
apt-get install -y build-essential nodejs
This means that my full Dockerfile
now looks like this:
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
RUN apt-get update && \
apt-get install -y wget && \
apt-get install -y gnupg2 && \
wget -qO- https://deb.nodesource.com/setup_6.x | bash - && \
apt-get install -y build-essential nodejs
WORKDIR /app
EXPOSE 14242
EXPOSE 44321
FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY ["MyAngularWebsite.csproj", ""]
RUN dotnet restore "/MyAngularWebsite.csproj"
COPY . .
WORKDIR "/src/"
RUN dotnet build "MyAngularWebsite.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "MyAngularWebsite.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "MyAngularWebsite.dll"]
...and... the results are exactly the same.
Why is NPM not installed?
Per @DannyB's comment, I tried bash-ing into the Docker container to run npm
directly:
docker exec -it mycontainer_id /bin/bash
...and when I tried to execute npm
I got an error saying "npm: command not found". So, I guess that's the reason that it's still not working.
I then tried executing each of the commands I added to the Dockerfile
in turn, directly in the bash shell. When I got to the line:
wget -qO- https://deb.nodesource.com/setup_6.x
...it executed without producing any output, but I realised that's because the -q
flag means "quiet mode", so I executed it again without the q
. This time, I got errors:
ERROR: The certificate of 'deb.nodesource.com' is not trusted.
ERROR: The certificate of 'deb.nodesource.com' hasn't got a known issuer.
Digging deeper, it turns out I get certificate-related errors even if I simply do:
curl https://www.google.com
This results in an error saying "SSL certificate problem: self signed certificate in certificate chain".
So, it seems that my container has trust issues :-).
Why is my container unable to make HTTPS connections?
Per this question, it seems that it's because I'm running in a corporate environment where SSL traffic through the firewall is intercepted/re-encrypted, and that I'll need to configure my Docker container to trust the corresponding certificate.
Assuming that's correct, hopefully I'll be able to fix the trust issues, then install NPM, and hopefully solve the original issue.
I think this question has moved rather off-topic now, though I'll continue to update it if I manage to make further progress.