Skip to content

Running ASP.NET Core Website in docker on a Raspberry Pi

In the current era, software has become incredibly powerful and cross-platform, on top of that even a developer DIY board Raspberry Pi has a lot to offer with the hardware becoming more powerful. Let us take a lot at how we can setup and run ASP.NET Core Web Application in docker on a Raspberry Pi.

The Story!

Everything starts with an itch to learn something new. So I set out to run ASP.NET Core on docker and found that my desktop was running Windows 10 Home edition. Docker desktop was not an option since its still in preview for Windows 10 Home and also need the latest Windows 10 update. Well one choice was to wait for the update and the other to find alternative options to get the work done.

That’s when I realized I have a Raspberry Pi 3B lying around unused. Earlier I had run Windows 10 IoT on RPI for building a prototype focused on RFID. But this time, I thought of learning something new with the *nix platform.

Well here we are ready to run Raspberry Pi OS (previously called Raspbian) for my docker and ASP.NET Core adventure. Raspberry Pi OS is based on the well-known Debian GNU/Linux operating system and uses a modified LXDE desktop environment called PIXEL or simply the Raspberry Pi Desktop.

If you have not installed .NET Core on your RPI, read my earlier post How to install .NET Core on Raspberry Pi

What is .NET Core?

.NET Core is a free and open-source, managed computer software framework for Windows, Linux, and macOS operating systems. It is a cross-platform successor to.NET Framework. The project is primarily developed by Microsoft and released under the MIT License. .NET Platform source is available on Github.

What is ASP.NET Core?

ASP.NET Core is a free and open-source web framework, which has a better performance than ASP.NET developed by Microsoft and the community. It is a modular framework that runs on both the full .NET Framework for Windows and also on the cross-platform .NET Core.

What is Docker?

Docker is a tool designed to make it easier to create, deploy and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and deploy it as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Docker host (Linux or Windows) machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code.

In a way, Docker is a bit like a virtual machine. But unlike a virtual machine, rather than creating a whole virtual operating system, Docker allows applications to use the same Linux/Windows kernel as the system that they’re running on and only requires applications be shipped with things not already running on the host computer. This gives a significant performance boost and reduces the size of the application.

In short, Docker is all about Application Virtualization so that you can host your application on any Operating System which supports docker.

How to install Docker on Raspberry Pi?

The following command from local RPI terminal or SSH remote terminal will install docker on RPI

> curl -sSL https://get.docker.com | sh

How to create ASP.NET Core App from CLI?

We are going to create a Hello World ASP.NET App for our example to reduce all the complexity of the Application itself. Here are the steps outlined.

  • Making sure we are in the home directory before starting
  • Create a folder for our helloweb application
  • Switch folder to newly created folder
  • Generate our helloweb app
  • Run the app to test it
> cd $HOME
> mkdir helloweb
> cd helloweb
> dotnet new web
The template "ASP.NET Core Empty" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on /home/pi/helloweb/helloweb.csproj...
  Determining projects to restore...
  Restored /home/pi/helloweb/helloweb.csproj (in 1.01 sec).

Restore succeeded.
> dotnew run
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /home/pi/helloweb

Testing and making sure the ASP.NET Core App works

From the last command above you can see that your newly created Web App is listening on localhost. It also provides 2 different ports, one for HTTP (5000) and another for HTTPS (5001).

From RPI console (not SSH), using browser, open http://localhost:5000/ to test if the browser shows Hello World!

If the browser shows “Hello World!” our first stage is done and we are ready to jump to docker.

How to create a Docker Image?

In order to run the application inside docker container, we need to create a docker image with our application. And before creating the docker image, we need to prepare a package or folder to bring our compiled application, all the related libraries and dependencies together. In .NET Core its done using the publish command.

So here we are creating a release build and .NET Core creates a folder called ‘publish’ with all the files required to run the application.

> dotnet publish -c Release
Microsoft (R) Build Engine version 16.6.0+5ff7b0c9e for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
  helloweb -> /home/pi/helloweb/bin/Release/netcoreapp3.1/helloweb.dll
  helloweb -> /home/pi/helloweb/bin/Release/netcoreapp3.1/publish/

Next task is to create the docker configuration file

Create a file called ‘Dockerfile’ in the project folder with the content given below.

From RPI terminal or SSH you can use the following command. Nano is a simple text editor. After typing the content, Hit CTRL+X to quit and it will prompt to save the file.

nano Dockerfile
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1

COPY bin/Release/netcoreapp3.1/publish App/
WORKDIR /App
ENTRYPOINT ["dotnet","helloweb.dll"]

Line 1: We are downloading a container base image from Microsoft Container Registry (mcr). Last portion means we are getting ASP.NET Core 3.1 specific base image for running our application.

Line 3: Here we are copying the files in the publish folder to a folder with the name ‘App’ inside the docker image we are creating.

Line 4: We are setting the working directory to the new folder called ‘App’

Line 5: This line specifies the entry point of the application and how to run it. You can see the dll name is the compiled application dll.

Following images can be used in the first line for different purposes as explained.

  • Console and other applications where only runtime is required
    FROM mcr.microsoft.com/dotnet/core/runtime:3.1
  • For development and compiling your app inside the docker image (larger image)
    FROM mcr.microsoft.com/dotnet/core/sdk:3.1
  • For Production/Release for final hosting
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1

Lets build the docker image

Let us build the docker image with our application inside it. Parameter -t denotes tag name for the image. Parameter -f points to the docker configuration file we created in the step above, and the dot is for current folder where the file resides. This step would take time depending on your internet speed since its downloading an image.

> sudo docker build -t hellowebsite-image -f Dockerfile .
Sending build context to Docker daemon  1.144MB
Step 1/4 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
3.1: Pulling from dotnet/core/aspnet
2dd003996c9a: Pull complete
52ae7ebf826a: Pull complete
d1cb8ce1104e: Pull complete
4b57ddfbb902: Pull complete
d216cb40879e: Pull complete
Digest: sha256:060ebef0165a38e28279f7fd4f12e33d35af1de879442d75dabbcb4bc536e55c
Status: Downloaded newer image for mcr.microsoft.com/dotnet/core/aspnet:3.1
 ---> 80940ea236f7
Step 2/4 : COPY bin/Release/netcoreapp3.1/publish App/
 ---> 3588a2675529
Step 3/4 : WORKDIR /App
 ---> Running in 6c6f6e58c662
Removing intermediate container 6c6f6e58c662
 ---> 08c578f36eb0
Step 4/4 : ENTRYPOINT ["dotnet","helloweb.dll"]
 ---> Running in 4c085624d52c
Removing intermediate container 4c085624d52c
 ---> 5e46cc24fdda
Successfully built 5e46cc24fdda
Successfully tagged hellowebsite-image:latest

Once docker image is successfully created we can use the following command to check the details. You can see the base image which got downloaded and then our image which has our application included named as ‘hellowebsite-image’.

> sudo docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
hellowebsite-image                     latest              5e46cc24fdda        22 seconds ago      186MB
mcr.microsoft.com/dotnet/core/aspnet   3.1                 80940ea236f7        3 weeks ago         186MB

How to run the website inside docker container?

Below command runs our ‘helloweb’ App from the docker image we created called ‘hellowebsite-image’. Parameter -it is for interactive TTY, parameter –rm is to remove the container once the App stops and -name parameter is to give a name to the container we will be running this docker image inside ‘hello-core-website’.

> sudo docker run -it --rm -p 5000:80 --name hello-core-website hellowebsite-image
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /App

How to check the list of containers running?

> sudo docker ps
CONTAINER ID        IMAGE                COMMAND                 CREATED             STATUS              PORTS                  NAMES
5b261762e7b3        hellowebsite-image   "dotnet helloweb.dll"   20 seconds ago      Up 19 seconds       0.0.0.0:5000->80/tcp   hello-core-website

Some useful docker commands

// Command to remove a docker image 
> sudo docker rm [IMAGE TAG]

// Command to remove a docker container
> sudo docker rmi [CONTAINER ID]

Conclusion

I hope this article helps to get you started with docker if you have an RPI in hand. I love the way .NET core is going with the cross-platform focus. Also very excited to see what .NET 5 and .NET 6 are going to bring to .NET developers.

Leave a comment