Raspberry Pi3上でDockerを用いて.NET Core2.0のコンソールアプリケーションを実行する方法の紹介

Raspberry Pi3上でDockerを用いて.NET Core2.0のコンソールアプリケーションを実行する方法の紹介

 資料少なくて辛かったのでまとめます。

 .NET CoreをLinux上で動かす方法についてはMSが詳しく解説してくれていますUbuntuCentOSなどの主要なOSについてはパッケージ管理システムを用いてサクッとインストールできるようになっているのですが、raspbianについては記載されていません。raspbianはdebian派生なのでdebian向けの資料を漁ればさくっと行けるかと考えてましたが、CPUアーキテクチャがx64を対象にした資料ばかりで難儀しました。

 最終的にDocker Imageを作成して実行環境を整えることが出来ました。本記事ではそのDocker Imageの使い方とDockerfile作成にあたって参考になった情報の紹介をします。

 なお、本記事で手に入るのはランタイム環境のみです。dotnet buildやdotnet restoreといった開発向け機能は利用できるようになりません。予め別環境でアプリケーションをビルドしておく必要がありますので注意してください。

対象読者

  • Raspberry Pi上で.Net Core2.0 Previewを動かしたいって人
  • それもDockerで!って人
  • OSとしてraspbianを利用している人(Ubuntuを含むdebian派生なら大体参考になるはず)
  • docker初心者。全コマンド、全オプションの解説まではしてませんが、忘備録兼ねてそこそこ詳しく書いてます。

早速見ていきましょう。

Dockerをインストールする

 raspbianにDockerをインストールします。下記コマンドを叩くといい感じにインストールしてくれます。簡単。

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

Raspberry Pi向けのDocker Imageを取得する

 下記コマンドでDockerHubからローカルにダウンロードできます。

$ docker pull kokeiro001/rpi-dotnet:2.0-runtime

ダウンロードしてきたDocker Imageのバージョンを表示してみる

 動作確認を兼ねて、下記コマンドで先程ダウンロードしたDocker Image内のdotnetのバージョン情報を表示してみます。

$ docker run --rm kokeiro001/rpi-dotnet:2.0-runtime dotnet --info
#=> Microsoft .NET Core Shared Framework Host
#=> 
#=>   Version  : 2.0.0-preview3-25424-01
#=>   Build    : 122309e7e7fb9bb233fe4910f822c28ec73f0957

 気が向いたらDocker Imageを更新するので、VersionやBuildの値はpullしてきたイメージ次第です。

Docker Imageの使用例

 Dockerを用いたアプリケーション実行方法にもいくつか種類がありますので紹介します。

 今回は例としてCowsay.Netを使用します。Releaseからビルド済みのバイナリをダウンロード・展開して使用します。中身はVisualStudio2017から発行したディレクトリをzipで固めてアップロードしただけのものです。

 wgetコマンドとunzipコマンドも使用します。インストールしておきましょう(デフォルトで入ってたっけ?覚えてないや)。

$ sudo apt-get update && sudo apt-get install -y wget unzip

ホストPC上に配置してあるアプリケーションをマウントしてアプリケーションを実行する

 まずはちょっとした動作確認にオススメの方法です。

 ホストPC上の/home/pi/内にCowsayNetアプリケーションを展開し、そいつをコンテナから実行させてみます。

$ cd ~/
$ wget https://github.com/kokeiro001/Cowsay.Net/releases/download/v0.0.1/CowsayNet.zip
$ unzip CowsayNet.zip

$ docker run --rm -v /home/pi/CowsayNet/:/app kokeiro001/rpi-dotnet:2.0-runtime dotnet /app/Cowsay.Net.dll 
#=>  _____
#=> < moo >
#=>  -----
#=>  \   ^__^
#=>   \  (oo)\_______
#=>      (__)\       )\/\
#=>          ||----w |
#=>          ||     ||

$ docker run --rm -v /home/pi/CowsayNet/:/app kokeiro001/rpi-dotnet:2.0-runtime dotnet /app/Cowsay.Net.dll "Hello World"
#=>  _____________
#=> < Hello World >
#=>  -------------
#=>    \   ^__^
#=>     \  (oo)\_______
#=>        (__)\       )\/\
#=>            ||----w |
#=>            ||     ||
#=> 

 Hello Worldのように引数を与えるとウシがその言葉を喋り、与えなかった場合はmooと喋ります。素晴らしい。

 docker runコマンドのオプションのちょっとした解説をば。

-v /home/pi/CowsayNet/:/app

 ホストPCの/home/pi/CowsayNet/ディレクトリをコンテナ内部の/appにマウントしています。ディレクトリが共有されてるような状態。ホストPCに配置されている/home/pi/CowsayNet/Cowsay.Net.dllに対して、コンテナ内部からは/app/Cowsay.Net.dllというパスでアクセスすることが出来ます。そいつをdotnet /app/Cowsay.Net.dll "Hello World"で実行しています。

 この方法はコンテナを操作することなく簡単に利用することが出来ますが、アプリケーションとランタイムが分離した状態となってしまうためポータビリティが落ちます。ちょっとしたテストの利用にとどめるのが良いと思います。

ランタイム用コンテナの内部で対話的に作業してアプリケーションを実行する

 アプリケーションの中身をホストに置きたくない、分離したくないという場合の選択肢の一つとして、ランタイム用コンテナを起動後、そのコンテナ内部でアプリケーションを実行する環境を整えてるという方法があります。

$ docker run -it --rm kokeiro001/rpi-dotnet:2.0-runtime

#=> -itオプションによってコンテナに接続されます。以下、コンテナ内部でのrootユーザーによる作業となります。

# apt-get update && apt-get install -y wget unzip
# mkdir /app
# cd /app
# wget https://github.com/kokeiro001/Cowsay.Net/releases/download/v0.0.1/CowsayNet.zip
# unzip CowsayNet.zip
# cd CowsayNet
# dotnet Cowsay.Net.dll "I love C#."

#=>  ____________
#=> < I love C#. >
#=>  ------------
#=>    \   ^__^
#=>     \  (oo)\_______
#=>        (__)\       )\/\
#=>            ||----w |
#=>            ||     ||
#=> 

 コンテナ内部でアプリケーションの実行バイナリの取扱を完結させることが出来ました。ホストPC側の環境に触れることがないため、気軽に実験的な作業を行うことが出来ます。ただし、この方法ではコンテナ内部で手作業で環境構築をする必要があり、環境を再現するのに手間がかかるというデメリットがあります。

ランタイム用イメージをベースに、アプリケーションを含めた新しいイメージを作成してアプリケーションを実行する

 Dockerfileを使う方法です。最終的にたどり着く方法。

 ホストPC上での操作で完結します。/home/pi/CowsayDocker/ディレクトリを作成し、次のようなDockerfileを配置します。

FROM kokeiro001/rpi-dotnet:2.0-runtime

ENV DOWNLOAD_URL https://github.com/kokeiro001/Cowsay.Net/releases/download/v0.0.1/CowsayNet.zip

RUN set -x \
    && apt-get update && apt-get install -y wget unzip \
    && cd /tmp \
    && wget $DOWNLOAD_URL \
    && unzip CowsayNet.zip -d /app \
    && rm CowsayNet.zip \
    && rm -rf /var/lib/apt/lists/*

ENTRYPOINT ["dotnet", "/app/CowsayNet/Cowsay.Net.dll"]

 下記コマンドでDocker Imageを作成し、実行します。

$ cd ~/CowsayDocker
$ docker build -t rpi-cowsay .
$ docker run --rm rpi-cowsay
#=>  _____
#=> < moo >
#=>  -----
#=>  \   ^__^
#=>   \  (oo)\_______
#=>      (__)\       )\/\
#=>          ||----w |
#=>          ||     ||

$ docker run --rm rpi-cowsay "I love GitHub."
#=>  ________________
#=> < I love GitHub. >
#=>  ----------------
#=>     \   ^__^
#=>      \  (oo)\_______
#=>         (__)\       )\/\
#=>             ||----w |
#=>             ||     ||
#=> 

 シャベッタァアアアアアアアアアアアアアアアアアアアアアア(今更)

 Dockerfileさえアレばどこでも再現が可能で、ホストPCもクリーンな状態に保つことができます。先述の2パターンを用いて「このコマンドでいける!」と流れを掴んだらDockerfileに落とし込むのが良さそうです。

 使い方の紹介は以上です~。快適な.NET Core on Raspberry Piライフを。

なぜ作成したのか(背景、ポエム)

 Discord.Netを用いたチャットボットをRaspberry Pi上で動かしてるのですが、Discord.Netをv0.9からv1.0にアップデートするにあたってどうしても.NET Core2.0ランタイム環境が必要になったためです。Linux上でDiscord.Netを動かす場合、v0.9ではmonoで全機能を動かせてたのでそっちを利用してたのですが、v1.0からは音声周りの機能が.NET Coreの、しかも2.0じゃないと動かなくなったためです。まだ.NET Coreってプレビュー版やんけ!しかもDiscord.NetもRC版だし!いつ環境変わるか分からんし、簡単に環境を更新できるようにしておきたいぞ!と思いdockerでの構築に勤しみました。着手してみたら出てくる資料はx64向けのものばかりだし英語のばっかだしでスゲー困りました。のでまとめました。

 Discord.Net用のランタイム環境をまとめたDocker Imageも用意したので、こっちもそのうち紹介します。というか、こっちを紹介するための下準備として本記事を書いたような感じ。もっとDiscord.Netが日本で流行って欲しい。

参考・関連リンク