Открытая платформа .NET Core работает практически на всем: Windows, Mac и десятке Linux-систем. Но еще есть SDK и Runtime. Раньше .NET Core SDK не поддерживался на чипах ARMv7/ARMv8, на которых работает Raspberry Pi. Но все изменилось. Подробнее о способах запуска под катом!



Эту статью написал Скотт Хансельман. Передаю ему слово.

Мне нравится Raspberry Pi. Это отличные компактные обучающие машины, и дети очень любят с ними играть. Даже если эти дети — взрослые, и они создают кластер из шести узлов Kubernetes Raspberry Pi.

NET Core теперь поддерживается в дистрибутивах Linux ARM32, например Raspbian и Ubuntu!

Примечание. .NET Core 2.1 поддерживается на Raspberry Pi 2+. Она не поддерживается на Pi Zero или других устройствах с чипом ARMv6. Для работы с .NET Core требуется чип ARMv7 или ARMv8, такой как ARM Cortex-A53. Специалисты из команды Azure IoT Edge используют образы .NET Core Bionic ARM32 Docker для поддержки разработчиков, пишущих на C# на устройствах Edge.

Запустить .NET Core на Raspberry Pi можно двумя способами.

Первый способиспользовать Docker. Это буквально самый быстрый и простой способ заставить .NET Core работать на Pi. Это кажется невероятным, но такие маленькие устройства Raspberry Pi отлично поддерживают контейнеры платформы Docker. Это можно сделать за считаные минуты. Для быстрой установки Docker вам понадобится:

curl -sSL https://get.docker.com | sh
sudo usermod -aG docker pi

После установки Docker необходимо войти в систему и выйти из нее. Посмотрите небольшой пример, чтобы убедиться в том, что .NET Core работает корректно. Вы можете посмотреть доступные теги Docker по адресу, а также узнать больше о шаблонах .NET Core Docker здесь.

Теперь я могу просто запустить Docker, а затем выполнить команду «dotnet --info», чтобы узнать о dotnet на моем 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

Это просто замечательно! Теперь я лишь запрашиваю dotnet: 2.1-sdk на Raspberry Pi (RPi), и поскольку они используют мультиархитектурные файлы Docker, платформа работает корректно. Если вы хотите использовать .NET Core с Docker на ARM32, вы можете использовать любой из следующих тегов.

Примечание. Первые три тега multi-arch и bionic для Ubuntu 18.04. Кодовое название stretch для Debian 9. Поэтому я использую 2.1-sdk, и он нормально работает на моем RPi, но я могу быть более конкретным, если захочу.

  • 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

Попробуйте сделать это за считанные минуты вот таким образом:

docker run --rm microsoft/dotnet-samples:dotnetapp

Вот он скачивает образ…



В предыдущих версиях Docker-файлов .NET Core это не получилось бы, если бы вы запустили x64-образ на ARM.

standard_init_linux.go:190: exec user process caused "exec format error"

Разные процессоры! Но с мультиархитектурными тегами от Кендры Хэйвенс из Microsoft все отлично работает в версии 2.1.

Docker имеет функцию мультиархитектурности, которую недавно начали использовать в microsoft/dotnet-nightly. В ближайшее время планируется перенести это на официальный репозиторий microsoft/dotnet. Функция мультиархитектурности позволяет использовать один тег для нескольких конфигураций машины. Без этой функции для каждой архитектуры/ОС/платформы потребуется уникальный тег. Например, тег microsoft/dotnet:1.0-runtime основан на Debian, а microsoft/dotnet:1.0-runtime-nanoserver на Nano Server. С мультиархитектурностью будет необходим лишь один общий тег microsoft/dotnet:1.0-runtime. Если взять этот тег из контейнерной среды Linux, то получится образ на основе Debian, тогда как если взять его из контейнерной среды Windows, то получится образ на основе Nano Server. Это помогает обеспечить единообразие тегов в среде Docker, что позволяет избежать путаницы.

В приведенных выше примерах я могу делать следующее:

Запускать заранее сконфигурированное приложение внутри образа Docker, например:
docker run --rm microsoft/dotnet-samples:dotnetapp

Запускать команды dotnet в SDK-образе, например:
docker run --rm -it microsoft/dotnet:2.1-sdk dotnet --info

Запускать интерактивный терминал в SDK-образе, например:
docker run --rm -it microsoft/dotnet:2.1-sdk

В качестве небольшого примера, здесь я перейду в контейнер и добавлю небольшое консольное приложение и запущу его, просто чтобы доказать, что это возможно. Все будет удалено, когда я выйду из контейнера.

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 in 15.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!

Если вы попробуете сами, то заметите, что команда «dotnet run» выполняется медленно. Это потому, что она выполняет восстановление, сборку и запуск. Компиляция проходит не слишком быстро на этих крошечных устройствах. Поэтому стоит делать как можно меньше работы. Вместо того чтобы все время запускать «dotnet run», я выполню команду «dotnet build», а затем «dotnet exec», которые выполняются очень быстро.

Если вы собираетесь пробовать Docker и .NET Core, то вам будут невероятно полезны эти ресурсы.

Создание приложений .NET Core с использованием Docker



Создание приложений .NET Core в контейнере


  • Разработка приложений .NET Core — этот пример показывает, как разрабатывать, собирать и тестировать приложения .NET Core с помощью Docker без установки .NET Core SDK.
  • Разработка приложений ASP.NET Core — в этом примере показано, как разрабатывать и тестировать базовые приложения ASP.NET с помощью Docker без установки .NET Core SDK.

Оптимизация размера контейнера



ARM32 / RASPBERRY PI



Мне кажется, что эти примеры очень полезные… Обязательно смотрите сами файлы Docker, так как они дадут вам огромное количество информации о том, как структурировать ваши собственные файлы. Возможность создавать многоэтапные файлы Docker имеет решающее значение при работе на небольшом устройстве, например RPi. Желательно делать как можно меньше работы, и пусть Docker автоматически кеширует столько слоев, сколько возможно. Если вы не продумаете этот момент, то в конечном итоге потратите в 10 раз больше времени на создание слоев образа для каждой сборки.

Перевод реального ASP.NET сайта на Docker с тестами!


Могу ли я перевести свой сайт с подкастами на Docker, а также собрать/тестировать/запустить его на Raspberry Pi? Да!

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"]

Замечательно. Теперь я могу выполнять команду «docker build .» на Raspberry Pi. Устройство восстановит, протестирует и построит его. Если тест окажется неудачным, то сборка Docker завершится неудачно.

Видите, там есть дополнительный раздел, с именем «testrunner», а затем после него «test?» Этот раздел не работает. Он устанавливает ENTRYPOINT, но этим никто никогда не пользуется… пока. ENTRYPOINT является неявным запуском, если находится в последней строке в файле Docker. Так сделано для того, чтобы я мог его найти, если захочу.

Я могу просто построить его и запустить вот так:

docker build -t podcast .
docker run --rm -it -p 8000:80 podcast

Заметка. Обратите внимание, что образ «runtime» — это microsoft/dotnet: 2.1-aspnetcore-runtime, а не microsoft/dotnet: 2.1-runtime. Также aspnetcore one предварительно включает в себя двоичный код, который нужен для запуска приложения ASP.NET, таким образом я могу просто включить одну ссылку на "/>" в csproj. Если не использовать базовый образ aspnetcore-runtime, то пришлось бы вручную активировать все пакеты ASP.NET Core, которые мне нужны. Использование базового образа может сделать финальные файлы образов больше, но это всего лишь баланс между удобством и размером. Решать вам. Вы можете вручную включить только нужные вам пакеты или использовать метапакет «Microsoft.AspNetCore.App» для удобства. Мой конечный образ «podcast» весил 205 мегабайт, что неплохо, но, конечно, если бы я хотел, я мог бы уменьшить его несколькими способами.

А если мне просто нужны результаты теста от Docker, я могу их получить! Это означает, что я могу запустить тест в контейнере Docker, смонтировать том между контейнером Linux и (теоретическим) узлом Windows, а затем открыть полученный .trx-файл в 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

Только посмотрите! Это результаты тестирования, которое выполнялось в контейнере Linux:



Вот и результат. Теперь у меня есть сайт подкастов, работающий в Docker на ARM32 Raspberry Pi 3, и я потратил на работу (написание файла Docker) всего лишь один час!



Второй способ. Вы дошли до этого момента? Вы можете просто установить .NET Core 2.1 SDK «на железо». Docker не нужен, просто скачайте tar.gz и настройте его. Я могу установить его на устройство типа RPI ARM32v7 Dockerfile. Заметьте, что при этом у меня есть общая среда выполнения ASP.NET Core *и* .NET Core SDK. В финальной версии вы получите SDK, в который будет включено все, в том числе 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

Да здравствует кросс-платформенность!

Комментарии (13)


  1. jehy
    16.07.2018 10:05
    +1

    До сих пор не понимаю наигранного удивления, с которым запускают всё на raspberry. У вас как бы там полноценный мощный компьютер с полноценной ос. Запуск там чего бы то ни было ничем не отличается от запуска этого софта на большом ящике. Откуда столько восторга? «И всё-таки, оно вертится»?


    1. MonkAlex
      16.07.2018 10:18
      -1

      Армы таки поддерживать надо, по моему в статье об этом написано достаточно явно


      1. Hydro
        16.07.2018 10:56

        надо кому?


      1. jehy
        16.07.2018 11:29

        Ну вы ещё скажите, что ARM это новая и мало кем поддерживаемая архитектура.


        1. MonkAlex
          16.07.2018 11:56

          Ну вот дотнетом раньше не поддерживалась. А теперь поддерживается.

          Что плохого то?


          1. jehy
            16.07.2018 11:59

            Ничего плохого — просто удивляет, что это преподносится как некий прорыв.


            1. Kubig
              16.07.2018 16:13

              Только для Microsoft


            1. ALexhha
              16.07.2018 17:11

              Прорывы бывают разные, а иногда и очень неожиданные

  1. x893
    16.07.2018 10:39

    Примерно такой же восторг, когда на питоне лампочкой моргают.
    Просто люди радуются жизни.


  1. vitaliy91
    16.07.2018 11:43

    А удалось ли кому запустить .NET Micro на STM32 микроконтроллерах? На сколько жизнеспособно будет такое решение?


    1. Hydro
      16.07.2018 16:48

      Лет 5 назад пробовал. Абсолютно нежизнеспособно.


  1. Chupakabra303
    16.07.2018 12:07

    Бедные SD-карточки.


  1. Mike-M
    16.07.2018 22:23

    После того как Microsoft похоронила свой проект .Net Micro Framework, я в их сторону больше не смотрю.