Deploy .NET Core microservices to ARM32

Posted on

Goal: Create .NET core microservices in Visual Studio and deploy them to an ARM32-based server, running Debian (in my case an Asus Tinkerboard running Linaro).

After plenty of research it became obvious that three mayor steps are needed to do so:

  1. Install dotnet
  2. Install and configure nginx (reverse proxy)
  3. Install and configure supervisor (service management daemon)

Finally, we should be able to create and deploy our first service.

This tutorial is a compilation of various sources, slightly modified to match the restrictions of the ARM32 platform.

Install .NET core runtime on ARM32

Source: Microsoft blog

Important: there is no .NET Core SDK for ARM32 devices, only a runtime, so you have to build your services on another device.

First, let’s install some basic packages:

sudo apt-get install curl libunwind8 gettext

Now, we can get the current .NET Core runtime using curl:

curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/release/2.0.0/dotnet-runtime-latest-linux-arm.tar.gz 

let’s unzip and move the runtime and create symlinks:

sudo mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet

sudo ln -s /opt/dotnet/dotnet /usr/local/bin

Finally, we can test the installation with dotnet –help - if it runs, everything is fine.

dotnet –help

Setup nginx server

Source: Hanselman blog

After installing the runtime, we need to install and setup nginx as a reverse proxy, which will later on allow us to connect to our .NET Core services. The process ist straight foreward:

$ sudo apt-get install nginx

Now, let’s start the service:

$ sudo service nginx start

The service needs some configuration - tweak the following file with the contents described later on:

$ sudo nano /etc/nginx/sites-available/default

This is the basic configuration for our nginx use case - listen to requests on port 80 and foreward them to our .NET Core service listening on port 5000 (default setting).

server {
    listen 80;
    location / {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Save the file an test the configuration, later reload the configuration:

sudo nginx -t
sudo nginx -s reload

Now, nginx is set up and redirecting services requests.

Setup supervisor

Source: Hackernoon

Last but not least, we have to configure our .NET Core service as a real service. Therefore, the supervisor daemon is needed. Again, the installation is simple:

sudo apt-get install supervisor

sudo service supervisor start

Create and deploy the first microservice

Sources: Hackernoon, GitHub

We are now prepared for the fascinating part - deploying our services to our ARM32-based server. The fascinating part - from my perspective - is, that services can be created and deployed from any .NET Core capable platform, e.g. WIN32. Just declare the target properly:

dotnet publish -c Release -r linux-arm -o publish

After compilation copy everythin to your server - using /var/nameOfService as the target directory and stop the supervisor service:

sudo service supervisor stop

Create a configuration file for every service you want to deploy:

$ sudo nano /etc/supervisor/conf.d/nameOfService.conf

Copy and adjust the contents below:

[program:nameOfService]
command=/usr/bin/dotnet /var/nameOfService/nameOfService.dll
directory=/var/nameOfService/
autostart=true
autorestart=true
stderr_logfile=/var/log/nameOfService.err.log
stdout_logfile=/var/log/nameOfService.out.log
environment=ASPNETCORE_ENVIRONMENT=Production
user=nameOfUser
stopsignal=INT

Afterwards, restart the supervisor service and check the logging of your .NET Core service:

sudo service supervisor start
sudo tail -f /var/log/nameOfService.out.log

Tada, we are up and running our first .NET Core service!