Открытая платформа .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 на Raspberry Pi можно двумя способами.
Первый способ — использовать Docker. Это буквально самый быстрый и простой способ заставить .NET Core работать на Pi. Это кажется невероятным, но такие маленькие устройства Raspberry Pi отлично поддерживают контейнеры платформы Docker. Это можно сделать за считаные минуты. Для быстрой установки Docker вам понадобится:
После установки Docker необходимо войти в систему и выйти из нее. Посмотрите небольшой пример, чтобы убедиться в том, что .NET Core работает корректно. Вы можете посмотреть доступные теги Docker по адресу, а также узнать больше о шаблонах .NET Core Docker здесь.
Теперь я могу просто запустить Docker, а затем выполнить команду «dotnet --info», чтобы узнать о dotnet на моем Pi.
Это просто замечательно! Теперь я лишь запрашиваю dotnet: 2.1-sdk на Raspberry Pi (RPi), и поскольку они используют мультиархитектурные файлы Docker, платформа работает корректно. Если вы хотите использовать .NET Core с Docker на ARM32, вы можете использовать любой из следующих тегов.
Попробуйте сделать это за считанные минуты вот таким образом:
Вот он скачивает образ…
В предыдущих версиях Docker-файлов .NET Core это не получилось бы, если бы вы запустили x64-образ на ARM.
Разные процессоры! Но с мультиархитектурными тегами от Кендры Хэйвенс из Microsoft все отлично работает в версии 2.1.
В приведенных выше примерах я могу делать следующее:
Запускать заранее сконфигурированное приложение внутри образа Docker, например:
Запускать команды dotnet в SDK-образе, например:
Запускать интерактивный терминал в SDK-образе, например:
В качестве небольшого примера, здесь я перейду в контейнер и добавлю небольшое консольное приложение и запущу его, просто чтобы доказать, что это возможно. Все будет удалено, когда я выйду из контейнера.
Если вы попробуете сами, то заметите, что команда «dotnet run» выполняется медленно. Это потому, что она выполняет восстановление, сборку и запуск. Компиляция проходит не слишком быстро на этих крошечных устройствах. Поэтому стоит делать как можно меньше работы. Вместо того чтобы все время запускать «dotnet run», я выполню команду «dotnet build», а затем «dotnet exec», которые выполняются очень быстро.
Если вы собираетесь пробовать Docker и .NET Core, то вам будут невероятно полезны эти ресурсы.
Мне кажется, что эти примеры очень полезные… Обязательно смотрите сами файлы Docker, так как они дадут вам огромное количество информации о том, как структурировать ваши собственные файлы. Возможность создавать многоэтапные файлы Docker имеет решающее значение при работе на небольшом устройстве, например RPi. Желательно делать как можно меньше работы, и пусть Docker автоматически кеширует столько слоев, сколько возможно. Если вы не продумаете этот момент, то в конечном итоге потратите в 10 раз больше времени на создание слоев образа для каждой сборки.
Могу ли я перевести свой сайт с подкастами на Docker, а также собрать/тестировать/запустить его на Raspberry Pi? Да!
Замечательно. Теперь я могу выполнять команду «docker build .» на Raspberry Pi. Устройство восстановит, протестирует и построит его. Если тест окажется неудачным, то сборка Docker завершится неудачно.
Видите, там есть дополнительный раздел, с именем «testrunner», а затем после него «test?» Этот раздел не работает. Он устанавливает ENTRYPOINT, но этим никто никогда не пользуется… пока. ENTRYPOINT является неявным запуском, если находится в последней строке в файле Docker. Так сделано для того, чтобы я мог его найти, если захочу.
Я могу просто построить его и запустить вот так:
А если мне просто нужны результаты теста от Docker, я могу их получить! Это означает, что я могу запустить тест в контейнере Docker, смонтировать том между контейнером Linux и (теоретическим) узлом Windows, а затем открыть полученный .trx-файл в Visual Studio!
Только посмотрите! Это результаты тестирования, которое выполнялось в контейнере 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.
Да здравствует кросс-платформенность!
Эту статью написал Скотт Хансельман. Передаю ему слово.
Мне нравится 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 Docker — этот пример создает, тестирует и запускает образец. Он включает и создает несколько проектов.
- Пример для ASP.NET Core Docker — этот пример демонстрирует, как использовать Docker с помощью веб-приложения ASP.NET Core.
Создание приложений .NET Core в контейнере
- Разработка приложений .NET Core — этот пример показывает, как разрабатывать, собирать и тестировать приложения .NET Core с помощью Docker без установки .NET Core SDK.
- Разработка приложений ASP.NET Core — в этом примере показано, как разрабатывать и тестировать базовые приложения ASP.NET с помощью Docker без установки .NET Core SDK.
Оптимизация размера контейнера
- Пример для .NET Core Alpine Docker — в этом примере собирается, тестируется и запускается приложение с использованием Alpine.
- Пример для автономных приложений NET Core — в этом примере собирается и запускается автономное приложение.
ARM32 / RASPBERRY PI
- Пример для .NET Core ARM32 Docker — в этом примере собирается и запускается приложение с Debian на ARM32 (работает на Raspberry Pi).
- Пример для ASP.NET Core ARM32 Docker — в этом примере собирается и запускается приложение ASP.NET Core с Debian на 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
Да здравствует кросс-платформенность!
jehy
До сих пор не понимаю наигранного удивления, с которым запускают всё на raspberry. У вас как бы там полноценный мощный компьютер с полноценной ос. Запуск там чего бы то ни было ничем не отличается от запуска этого софта на большом ящике. Откуда столько восторга? «И всё-таки, оно вертится»?
MonkAlex
Армы таки поддерживать надо, по моему в статье об этом написано достаточно явно
Hydro
надо кому?
jehy
Ну вы ещё скажите, что ARM это новая и мало кем поддерживаемая архитектура.
MonkAlex
Ну вот дотнетом раньше не поддерживалась. А теперь поддерживается.
Что плохого то?
jehy
Ничего плохого — просто удивляет, что это преподносится как некий прорыв.
Kubig
Только для Microsoft
ALexhha
x893
Примерно такой же восторг, когда на питоне лампочкой моргают.
Просто люди радуются жизни.
vitaliy91
А удалось ли кому запустить .NET Micro на STM32 микроконтроллерах? На сколько жизнеспособно будет такое решение?
Hydro
Лет 5 назад пробовал. Абсолютно нежизнеспособно.
Chupakabra303
Бедные SD-карточки.
Mike-M
После того как Microsoft похоронила свой проект .Net Micro Framework, я в их сторону больше не смотрю.