Monday, February 18, 2019

A21-Adding docker support to ASP.NET Core SPA Application

This post is about my experience adding docker support to the A100 website. You can find the github repo here.

Disclaimer: I am a beginner to docker and Linux, and I don’t know what I am doing while trying to configure docker but I just wanted to share what steps I took and where my frustrations were with respect to dockerizing existing ASP.NET Core SPA applications.

I thought to take a spin at docker and decided to dockerize the A100 website. I knew that you could just right click the project and click on “Add Docker Support” to dockerize an existing application.  So I did that and then I clicked on F5 to debug the website inside a docker container from Visual Studio. It didn’t worked because there was no node installed.

No node installed on the base dotnet runtime image

The A100 ASP.NET Core application is a spa application built using the default Angular template. The backend is ASP.NET Web API and front-end is using Angular, all within a single Visual Studio project. The spa application depends on npm and node during compile time as well as runtime. The docker file that is generated uses nano server as the base image, which has the dotnet core runtime and nothing else.  There is no node installed in the base nano server image.

Not an easy way to install node on nano server without PowerShell

This led me to the path of installing node on the nano server, but there is no easy way to install node because PowerShell is not available in those nano server images.

Mitul, curl.exe and tar.exe are available on nano server, why you didn’t try that”- as you might suggest. I did try that, however, I couldn’t unzip the .zip file that I downloaded from the website using tar.exe. I tried tar.exe –xf multiple times but it didn’t work. Maybe there is a bug in the tar.exe on nano server. It kept saying “Unrecognized format”. Maybe tar doesn’t support .zip files. At this point, I gave up the idea of using a window server container image since I couldn’t get it to work.

But Mitul, you could have used multi stage builds in docker image to download the file inside server core and then copied into nano server image. Why didn’t you try that?” – as you might suggest again. I didn’t realize this at this point and I learned that that’s how dotnet is building their base image. This is an option that I will try next. I hope it would work.

I followed this github issue to successfully install nodejs.

Node-sass doesn’t work on Linux container

I switched to Linux containers and then regenerated docker file again and this time too the base image didn’t had node installed on it. So I had to install nodejs both on the sdk image and the runtime image because you need once for compiling and another one during runtime. Finally, I was successfully able to install node. Yay! But when I tried to build docker image, it errored out complaining that node-sass is not suitable or not available for your environment. I came across the suggestion that I might have to rebuild it. I tried rebuilding node-sass package and this time I was successfully able to rebuild node-sass. However, I during runtime I kept getting error that could not generate .css from sass and it was node-sass related issue. It didn’t work.

Error: Missing binding /app/ClientApp/node_modules/node-sass/vendor/linux-x64-67/binding.node
Node Sass could not find a binding for your current environment: Linux 64-bit with Node.js 11.x

Found bindings for the following environments:
   - Windows 64-bit with Node.js 10.x
   - Windows 64-bit with Node.js 11.x

This usually happens because your environment has changed since running `npm install`.
Run `npm rebuild node-sass` to download the binding for your current environment.

My cross platform dream was vanishing quickly at this point. I was questioning my approach of developing in windows and hosting it in linux. Should I have developed inside a Linux environment like Windows Subsystem for Linux (WSL) instead? Since node-sass was giving issues, I decided to ditch sass and use scss. But I realized that scss is sass itself. Its newer version is called scss and it still requires node-sass. I was getting really frustrated. Finally, I switched to plain .css for the A100 website.

This step worked and I was able to do F5 and run the website from inside a Linux container. It might seem like that in one or two tries this thing worked for me. No. I spent one and half day in trying to figure this thing out with multiple attempts at building a docker image. I realized that there are few things where we can improve this experience for new users.

Provide alternate ways of creating images with node installed

I understand that ASP.NET Core team wants to keep the docker images as lean as possible but please provide documentation on how we can easily install node on nano server. Maybe there is an I was not able to find it. A better approach would be that when you try to click on “Add Docker Support” inside Visual Studio, and if this is a spa application, then provide a message or add comments to the docker file indicating that there is no node installed and please follow this article to install node in this docker container.

Node-sass npm package to be fixed

The node-sass package has given me the maximum issues. I do not understand that why would node-sass not work on Linux. Inside of package.json, there is nothing specific related to windows then when it tries to install node-sass on Linux, then it should try to install node-sass that is native to Linux. Why it is failing to work properly on Linux? I have no idea. It would be nice if this is addressed as I am not using sass or scss for now. I could be wrong but I have seen in tutorials or on youtube videos that most people are using sass or scss. If this is the case then this has to be improved.

I learnt that I need to read more documentation regarding docker, Linux and ASP.NET Core. If you have suggestions then please provide me in improving my understanding of docker.