.NET Core + Docker on Raspberry Pi. Is it legal?
- Transfer
The open .NET Core platform works on almost everything: Windows, Mac and a dozen Linux systems. But there is still the SDK and Runtime. Previously, the .NET Core SDK was not supported on ARMv7 / ARMv8 chips that run Raspberry Pi. But everything has changed. Read more about how to run under the cut!

This article was written by Scott Hanselman . Give him the word.
I like the Raspberry Pi. These are great compact learning machines, and kids love to play with them. Even if these children are adults, and they create a cluster of six Kubernetes Raspberry Pi nodes .
NET Core is now supported in Linux distributions of ARM32, such as Raspbian and Ubuntu !
There are two ways to launch .NET Core on the Raspberry Pi.
The first way is to use Docker . This is literally the fastest and easiest way to get .NET Core to work on Pi. This seems incredible, but such small Raspberry Pi devices perfectly support Docker platform containers. This can be done in minutes. To quickly install Docker you will need:
After installing Docker, you need to log in and log out. See a small example to make sure that .NET Core works correctly. You can see the available Docker tags at , as well as learn more about .NET Core Docker templates here .
Now I can just run Docker, and then execute the “dotnet --info” command to find out about dotnet on my Pi.
This is just great! Now I just request dotnet: 2.1-sdk on Raspberry Pi (RPi), and since they use Docker multi-architecture files, the platform works correctly. If you want to use .NET Core with Docker on the ARM32 , you can use any of the following tags.
Try to do it in minutes like this:
Here it downloads the image ...

In previous versions of the .cker Core Docker files, this would not have happened if you ran the x64 image on ARM.
Different processors! But with Microsoft's multi- architecture tags from Kendra Havens from Microsoft, everything works fine in version 2.1.
In the examples above, I can do the following:
Run a pre-configured application inside a Docker image, for example:
Run dotnet commands in an SDK image, for example:
Run an interactive terminal in an SDK image, for example:
As a small example, here I will go to the container and I will add a small console application and run it, just to prove that it is possible. Everything will be deleted when I exit the container.
If you try it yourself, you will notice that the dotnet run command is running slowly. This is because it performs restoration, build, and launch. The compilation doesn't go too fast on these tiny devices. Therefore it is worth doing as little work as possible. Instead of running “dotnet run” all the time, I will execute the “dotnet build” command, and then “dotnet exec”, which run very quickly.
If you are going to try Docker and .NET Core, then these resources will be extremely useful to you .
It seems to me that these examples are very useful ... Be sure to see the Docker files themselves, as they will give you a wealth of information on how to structure your own files. The ability to create multistep Docker files is crucial when working on a small device, such as RPi. It’s advisable to do as little work as possible, and let Docker automatically cache as many layers as possible. If you don’t think about this point, you’ll end up spending 10 times more time creating image layers for each assembly.
Can I translate my site with podcasts to Docker, as well as build / test / run it on Raspberry Pi? Yes!
Wonderful. Now I can execute the “docker build.” Command on the Raspberry Pi. The device will restore, test and build it. If the test fails, the Docker build fails.
You see, there is an additional section called "testrunner", and then after it "test?" This section does not work. He sets ENTRYPOINT, but no one ever uses it ... yet. ENTRYPOINT is an implicit start if it is in the last line in the Docker file. This is done so that I can find it if I want.
I can just build it and run it like this:
And if I just need the Docker test results , I can get them! This means that I can run the test in the Docker container, mount the volume between the Linux container and the (theoretical) Windows node, and then open the resulting .trx file in Visual Studio!
Just look! These are the test results that were performed in the Linux container:

This is the result. Now I have a podcast site running Docker on the ARM32 Raspberry Pi 3, and I spent only one hour at work (writing the Docker file)!

The second way. Have you got to this point? You can simply install the .NET Core 2.1 SDK on hardware. Docker is not needed, just download tar.gz and configure it. I can install it on an RPI ARM32v7 Dockerfile device . Notice that I have a common ASP.NET Core * runtime and the * .NET Core SDK. In the final version you will receive an SDK in which everything will be included, including ASP.NET.
Long live cross-platform!

This article was written by Scott Hanselman . Give him the word.
I like the Raspberry Pi. These are great compact learning machines, and kids love to play with them. Even if these children are adults, and they create a cluster of six Kubernetes Raspberry Pi nodes .
NET Core is now supported in Linux distributions of ARM32, such as Raspbian and Ubuntu !
Note. .NET Core 2.1 is supported on Raspberry Pi 2+. It is not supported on Pi Zero or other devices with an ARMv6 chip. An ARMv7 or ARMv8 chip, such as ARM Cortex-A53, is required to work with .NET Core. Experts from the Azure IoT Edge team use .NET Core Bionic ARM32 Docker images to support developers writing in C # on Edge devices .
There are two ways to launch .NET Core on the Raspberry Pi.
The first way is to use Docker . This is literally the fastest and easiest way to get .NET Core to work on Pi. This seems incredible, but such small Raspberry Pi devices perfectly support Docker platform containers. This can be done in minutes. To quickly install Docker you will need:
curl -sSL https://get.docker.com | sh
sudo usermod -aG docker pi
After installing Docker, you need to log in and log out. See a small example to make sure that .NET Core works correctly. You can see the available Docker tags at , as well as learn more about .NET Core Docker templates here .
Now I can just run Docker, and then execute the “dotnet --info” command to find out about dotnet on my Pi.
pi@raspberrypi:~ $ docker run --rm -it microsoft/dotnet:2.1-sdk dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 2.1.300-rc1-008673
Commit: f5e3ddbe73
Runtime Environment:
OS Name: debian
OS Version: 9
OS Platform: Linux
RID: debian.9-x86
Base Path: /usr/share/dotnet/sdk/2.1.300-rc1-008673/
Host (useful for support):
Version: 2.1.0-rc1
Commit: eb9bc92051
.NET Core SDKs installed:
2.1.300-rc1-008673 [/usr/share/dotnet/sdk]
.NET Core runtimes installed:
Microsoft.NETCore.App 2.1.0-rc1 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
To install additional .NET Core runtimes or SDKs:
https://aka.ms/dotnet-download
This is just great! Now I just request dotnet: 2.1-sdk on Raspberry Pi (RPi), and since they use Docker multi-architecture files, the platform works correctly. If you want to use .NET Core with Docker on the ARM32 , you can use any of the following tags.
Note. The first three tags are multi-arch and bionic for Ubuntu 18.04. The codename is stretch for Debian 9. So I use 2.1-sdk, and it works fine on my RPi, but I can be more specific if I want.
- 2.1-sdk
- 2.1-runtime
- 2.1-aspnetcore-runtime
- 2.1-sdk-stretch-arm3
- 2.1-runtime-stretch-slim-arm32v7
- 2.1-aspnetcore-runtime-stretch-slim-arm32v7
- 2.1-sdk-bionic-arm32v7
- 2.1-runtime-bionic-arm32v7
- 2.1-aspnetcore-runtime-bionic-arm32v7
Try to do it in minutes like this:
docker run --rm microsoft/dotnet-samples:dotnetapp
Here it downloads the image ...

In previous versions of the .cker Core Docker files, this would not have happened if you ran the x64 image on ARM.
standard_init_linux.go:190: exec user process caused "exec format error"
Different processors! But with Microsoft's multi- architecture tags from Kendra Havens from Microsoft, everything works fine in version 2.1.
Docker has a multi -architecture feature that has recently begun to be used in microsoft / dotnet-nightly . In the near future it is planned to transfer it to the official Microsoft / dotnet repository .. The multiarch feature allows the use of a single tag for multiple machine configurations. Without this function, a unique tag is required for each architecture / OS / platform. For example, the microsoft / dotnet tag: 1.0-runtime is based on Debian, and microsoft / dotnet: 1.0-runtime-nanoserver on the Nano Server. With multiarchitecture, only one common microsoft / dotnet tag will be needed: 1.0-runtime. If you take this tag from the Linux container environment, you will get a Debian based image, whereas if you take it from a Windows container environment, you will get an image based on the Nano Server. This helps ensure consistency of tags in the Docker environment, thus avoiding confusion.
In the examples above, I can do the following:
Run a pre-configured application inside a Docker image, for example:
docker run --rm microsoft/dotnet-samples:dotnetapp
Run dotnet commands in an SDK image, for example:
docker run --rm -it microsoft/dotnet:2.1-sdk dotnet --info
Run an interactive terminal in an SDK image, for example:
docker run --rm -it microsoft/dotnet:2.1-sdk
As a small example, here I will go to the container and I will add a small console application and run it, just to prove that it is possible. Everything will be deleted when I exit the container.
pi@raspberrypi:~ $ docker run --rm -it microsoft/dotnet:2.1-sdk
root@063f3c50c88a:/# ls
bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
root@063f3c50c88a:/# cd ~
root@063f3c50c88a:~# mkdir mytest
root@063f3c50c88a:~# cd mytest/
root@063f3c50c88a:~/mytest# dotnet new console
The template "Console Application" was created successfully.
Processing post-creation actions...
Running 'dotnet restore'on /root/mytest/mytest.csproj...
Restoring packages for /root/mytest/mytest.csproj...
Installing Microsoft.NETCore.DotNetAppHost 2.1.0-rc1.
Installing Microsoft.NETCore.DotNetHostResolver 2.1.0-rc1.
Installing NETStandard.Library 2.0.3.
Installing Microsoft.NETCore.DotNetHostPolicy 2.1.0-rc1.
Installing Microsoft.NETCore.App 2.1.0-rc1.
Installing Microsoft.NETCore.Platforms 2.1.0-rc1.
Installing Microsoft.NETCore.Targets 2.1.0-rc1.
Generating MSBuild file /root/mytest/obj/mytest.csproj.nuget.g.props.
Generating MSBuild file /root/mytest/obj/mytest.csproj.nuget.g.targets.
Restore completed in15.8 sec for /root/mytest/mytest.csproj.
Restore succeeded.
root@063f3c50c88a:~/mytest# dotnet run
Hello World!
root@063f3c50c88a:~/mytest# dotnet exec bin/Debug/netcoreapp2.1/mytest.dll
Hello World!
If you try it yourself, you will notice that the dotnet run command is running slowly. This is because it performs restoration, build, and launch. The compilation doesn't go too fast on these tiny devices. Therefore it is worth doing as little work as possible. Instead of running “dotnet run” all the time, I will execute the “dotnet build” command, and then “dotnet exec”, which run very quickly.
If you are going to try Docker and .NET Core, then these resources will be extremely useful to you .
Creating .NET Core Applications with Docker
- Sample for .NET Core Docker - this example creates, tests and runs a sample. It includes and creates several projects.
- ASP.NET Core Docker Example - This example demonstrates how to use Docker using an ASP.NET Core web application.
Creating .NET Core applications in a container
- .NET Core Application Development - This example shows how to develop, build, and test .NET Core applications using Docker without installing the .NET Core SDK.
- ASP.NET Core Application Development - This example shows how to develop and test basic ASP.NET applications using Docker without installing the .NET Core SDK.
Container size optimization
- Example for .NET Core Alpine Docker - in this example , an application is built, tested and launched using Alpine.
- Example for stand-alone applications. NET Core - in this example , a stand-alone application is built and run.
ARM32 / RASPBERRY PI
- Example for .NET Core ARM32 Docker - in this example , an application is assembled and launched from Debian to ARM32 (runs on Raspberry Pi).
- Example for ASP.NET Core ARM32 Docker - in this example , an ASP.NET Core application is built and launched from Debian on ARM32 (runs on Raspberry Pi).
It seems to me that these examples are very useful ... Be sure to see the Docker files themselves, as they will give you a wealth of information on how to structure your own files. The ability to create multistep Docker files is crucial when working on a small device, such as RPi. It’s advisable to do as little work as possible, and let Docker automatically cache as many layers as possible. If you don’t think about this point, you’ll end up spending 10 times more time creating image layers for each assembly.
Translation of a real ASP.NET site to Docker with tests!
Can I translate my site with podcasts to Docker, as well as build / test / run it on Raspberry Pi? Yes!
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.sln .
COPY hanselminutes.core/*.csproj ./hanselminutes.core/
COPY hanselminutes.core.tests/*.csproj ./hanselminutes.core.tests/
RUN dotnet restore
# copy everything else and build app
COPY . .
WORKDIR /app/hanselminutes.core
RUN dotnet build
FROM build AS testrunner
WORKDIR /app/hanselminutes.core.tests
ENTRYPOINT ["dotnet", "test", "--logger:trx"]
FROM build AS test
WORKDIR /app/hanselminutes.core.tests
RUN dotnet test
FROM build AS publish
WORKDIR /app/hanselminutes.core
RUN dotnet publish -c Release -o out
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime
WORKDIR /app
COPY --from=publish /app/hanselminutes.core/out ./
ENTRYPOINT ["dotnet", "hanselminutes.core.dll"]
Wonderful. Now I can execute the “docker build.” Command on the Raspberry Pi. The device will restore, test and build it. If the test fails, the Docker build fails.
You see, there is an additional section called "testrunner", and then after it "test?" This section does not work. He sets ENTRYPOINT, but no one ever uses it ... yet. ENTRYPOINT is an implicit start if it is in the last line in the Docker file. This is done so that I can find it if I want.
I can just build it and run it like this:
docker build -t podcast .
docker run --rm -it -p 8000:80 podcast
The note.Note that the runtime image is microsoft / dotnet: 2.1-aspnetcore-runtime, not microsoft / dotnet: 2.1-runtime. Also, aspnetcore one tentatively includes the binary code that is needed to run an ASP.NET application, so I can simply include one link to the "/>" in the csproj. If you do not use the base aspnetcore-runtime image, you would have to manually activate all the ASP.NET Core packages I need. Using a base image can make the final image files larger, but this is just a balance between convenience and size. You decide. You can manually include only the packages you need or use the “Microsoft.AspNetCore.App” meta-package for convenience. My final podcast image weighed 205 megabytes, which is not bad, but, of course, if I wanted to, I could reduce it in several ways.
And if I just need the Docker test results , I can get them! This means that I can run the test in the Docker container, mount the volume between the Linux container and the (theoretical) Windows node, and then open the resulting .trx file in Visual Studio!
docker build --pull --target testrunner -t podcast:test .
docker run --rm -v D:\github\hanselminutes-core\TestResults:/app/hanselminutes.core.tests/TestResults podcast:test
Just look! These are the test results that were performed in the Linux container:

This is the result. Now I have a podcast site running Docker on the ARM32 Raspberry Pi 3, and I spent only one hour at work (writing the Docker file)!

The second way. Have you got to this point? You can simply install the .NET Core 2.1 SDK on hardware. Docker is not needed, just download tar.gz and configure it. I can install it on an RPI ARM32v7 Dockerfile device . Notice that I have a common ASP.NET Core * runtime and the * .NET Core SDK. In the final version you will receive an SDK in which everything will be included, including ASP.NET.
$ sudo apt-get -y update
$ sudo apt-get -y install libunwind8 gettext
$ wget https://dotnetcli.blob.core.windows.net/dotnet/Sdk/2.1.300-rc1-008673/dotnet-sdk-2.1.300-rc1-008673-linux-arm.tar.gz
$ wget https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/2.1.0-rc1-final/aspnetcore-runtime-2.1.0-rc1-final-linux-arm.tar.gz
$ sudo mkdir /opt/dotnet
$ sudo tar -xvf dotnet-sdk-2.1.300-rc1-008673-linux-arm.tar.gz -C /opt/dotnet/
$ sudo tar -xvf aspnetcore-runtime-2.1.0-rc1-final-linux-arm.tar.gz -C /opt/dotnet/
$ sudo ln -s /opt/dotnet/dotnet /usr/local/bin
$ dotnet --info
Long live cross-platform!