Topicsの2022年8月19日号でも紹介されているように、Microsoftが提供するクロスプラットフォームな開発フレームワークである「.NET」のUbuntu向けパッケージが公式リポジトリからも提供されることになりました。今回はこれを用いてC#でWindows向けのプログラムを作ってみましょう。実は前から存在した.NETパッケージ「.NET」はMicrosoftが提供する開発プラットフォームではありますが、MITライセンスで公開されたオープンソースプログラムでもあります[1]。.NETを使えば、Windowsだけでなく、macOSやLinuxなどの各プラットフォームに対応し、サーバーアプリケーションを含むCLIツールをC#で作成できます[2]。Frameworkはほぼプロプライエタリでした。5としてリリースされたのです。6はその次のバージョンの.NETとなります。Linux版の.NETはまだGUIアプリケーションに正式には対応していません。UI)もLinuxはまだサポート対象外です。Frameworkのオープンソース実装としては昔からMonoが存在しました。Monoはモバイルアプリも含めたクロスプラットフォームなフレームワークであるXamarinで採用され、「⁠なんやかんや」あってXamarinはMonoごとMicrosoftに買収されることになります。6ではこのモバイルアプリ向けであるXamarinも統合し、名実ともに「クロスプラットフォームな開発フレームワーク」となりました。UbuntuのリポジトリにはMono関連パッケージも残っています。よって単純にC#でプログラミングするなら、Monoを使う手もあります。SDKや.NETランタイムをaptコマンドでインストールできるようにしていました[3]。ユーザーや開発者は必要に応じてMicrosoftが提供するリポジトリを追加するだけで、Ubuntuでも.NET環境を構築できたのです[4]。snapパッケージも作っていましたが、今回の公式リポジトリでの配布によってsnap版は廃止されたようです。ライセンスに問題ないのであれば、Debianのリポジトリ取り込まれても良さそうではあるものの、現時点ではまだ取り込まれていません。SDKも含める」というアグレッシブな方法でこの問題を回避しています。結果的にソースパッケージのサイズが600MiBと、おかしな値になりました。ここまでの話をまとめると、今回の「.NETのUbuntu向けパッケージ」は、単に次のような、どちらかというと政治的な話でしかありません。MicrosoftはWSLに続いて.NETに関してもCanonicalと協力する.NETのSDKやランタイムを、Canonicalがパッケージングし公式リポジトリから提供するCanonicalは.NETのSDKやランタイムのセキュリティアップデートに対応する.NETランタイムが入った小さなDockerイメージを提供する一般的なユーザーにとっては、「⁠.NETアプリの導入がより簡単になる」という利点はあるものの、そもそも.NETアプリの大半を占めるGUIアプリは動きません。PowerShellがインストールしやすくなるかもしれない、ぐらいでしょうか。開発ユーザーにとっては、開発環境の構築が「ちょっとだけ」楽になります。それ以上に、Ubuntuユーザーの環境への.NETランタイムのランタイムのインストールが簡単になったために、Debianパッケージで配布する場合も、依存関係に.NETのパッケージ名だけを書けば良いようになりました。今後.NETベースのCLIアプリやWebアプリが比較的簡単にインストールできるようになるかもしれません。第435回の「PowerShellをUbuntuにインストール」で紹介したPowerShellは、.NET製のアプリケーションです。PowerShell自体はすでにMicrosoftによってUbuntu版のインストール方法がまとめられていますが、このような.NETソフトウェアがどんどんUbuntuでも使えるようになる可能性はあります。ひとつは、サーバーアプリケーションフレームワークであるASP.NETとの親和性です。SDKを採用しています。これらのようなASP.NETベースのアプリケーションも、UbuntuのリポジトリやLinux版のコンテナに取り込みやすくなることでしょう。LTSに取り込まれた.NETパッケージは、主に次の3種類のパッケージに分類できます。.NETアプリケーションの開発時にインストールする。6のアプリケーションを実行するために必要なランタイム。任意の.NETバイナリを実行だけしたい場合にインストールする。6のサーバーソフトウェアを実行するために必要なランタイム。サーバー用のライブラリが追加されている。ビルドする際はdotnet6をインストールし、実行するだけなら用途に応じてdotnet-runtime-6.0かapsnetcore-runtime-6.0のどちらかをインストールするという形です。dotnet6パッケージをインストールして、.NETアプリケーションをビルドしてみましょう。dotnet6アプリケーションの作成する際は「テンプレート」を指定します。今回は「console」テンプレートを利用しましょう。succeeded.テンプレートについては、SDKのドキュメントを参照してください。--list」を実行すれば、Ubuntu上で使用できるテンプレート一覧を確認できます。Test/xUnit今回はconsoleテンプレートを「MyApp」という名前で作成しました。実際に作られたファイルを見てみましょう。World!」を表示するだけのシンプルなプログラムですね。run」でプログラムをビルドし実行してくれます。World!試しに生成されたバイナリを確認してみましょう。Windows」と表示されるPE32バイナリも作られています。これも「Linux上でバイナリを実行するのに必要なライブラリ」です。実は.NETのランタイムライブラリはPEフォーマットでビルドされているのです。次に同じソースコードを「Windows向け」にビルドしてみましょう。buildに「-r」オプションで「ランタイム識別子」を指定する必要があります。64ビット版のWindowsなら「win-x64」ですし、バージョン指定するなら「win10-x6」になります。Linuxなら「linux-x64⁠」⁠、macOSなら「osx-x64」のように指定できますし、バージョンやディストリビューション、CPU固有の識別子も存在します。ランタイム識別子を指定する場合は、「⁠--self-contained」も必須のオプションとなります。これは実行用の.NETライブラリ一式をビルドディレクトリに生成するかどうかを指定するオプションです。「⁠true」なら生成し、「⁠false」なら生成しません。ビルドディレクトリをアーカイブして成果物にしたいなら、trueにする必要があるでしょう。.NETは複数のプラットフォームのクロスビルドをサポートしています。SDKをインストールしたUbuntuのコンテナイメージをひとつ用意しておけば、CIを使って簡単にすべてのプラットフォーム向けのバイナリを自動生成できるというわけです。シングルバイナリの生成方法もうひとつ、.NET関連のランタイムをシングルバイナリにまとめる方法も紹介しておきましょう。publish」で整理します。これはバイナリと必要なランタイム類を整理し、publishディレクトリに保存するコマンドです。普通にpublishすると次のようになります。bin/Debug/net6.0/publish/MyAppこのときの.NETバイナリ(MyApp)を実行するためには、MyApp.dllも、.NETランタイムも必要になります。そこで「PublishSingleFile」を設定してpublishしてみましょう。bin/Debug/net6.0/linux-x64/MyApp「PublishSingleFile」を指定する際は、「⁠-r」オプションによるランタイム識別子と「--self-contained」も指定する必要があります。false」なので.NETランタイムは同梱していません。サイズは少し大きくなっています。これはMyApp.dllがMyAppに同梱されたことによるものです。これにより「.NETランタイムがインストールされている環境」であれば、MyAppバイナリだけで実行が可能になります。true」を指定してみましょう。bin/Debug/net6.0/linux-x64/publish/MyAppファイルサイズが一気に大きくなりましたね。必要な.NETランタイムもバイナリの中に同梱されたことになります。このバイナリは「.NETランタイムがインストールされていない環境」でも実行可能です。様々な環境で利用する.NETアプリケーションを作るなら、シングルバイナリにしておくと良いでしょう。ちなみに「PublishSingleFile」はcsprojファイルに記述できます。Webアプリケーションの作成CLIアプリケーションとして、Webアプリケーションのテンプレートも使ってみましょう。succeeded.テンプレートに「webapp」を指定するだけで、その他は一緒です。World!」に比べて若干複雑になっていますね。これはシンプルなWebサーバーを実現するためのプログラムです。/home/ubuntu/temp/dotnet/MyService/今回はプロセスが残り続けています。HTTPSとして「https://localhost:7039」が、HTTPとして「http://localhost:5183」が用意されていますので、curl等でアクセスしてみましょう。/></head><body>(後略)無事にコンテンツが表示されました。「ASP.NET」は.NETでウェブアプリケーションを構築するためのランタイムです。.NETランタイムが公式パッケージで提供されることで、APP.NETでアプリケーションサービスを提供している場合もコンテナでの配布が楽になります。.NETのDebianパッケージはそれなりに大きなサイズなので、容量が小さくなるように対応したいかもしれません。そこで同時に登場したのが、ChiselベースのOCIイメージです。このChiselは現在開発中のGo言語のコマンドで、「⁠本当に最低限のバイナリしか含まないコンテナイメージ」を作るツールとなります。LTSのコンテナイメージをベースに、.NETバイナリが動作するために必要なglibcや証明書関連のライブラリ以外を全部削除したrootfsを作成し、それをコンテナイメージに変換するのです。結果的に、次のようなファイルサイズになっています。ubuntu/dotnet-deps(mcr.microsoft.com/dotnet/nightly/runtime-deps:6.0-jammy-chiseled⁠)⁠:12.9MBubuntu/dotnet-runtime(mcr.microsoft.com/dotnet/nightly/runtime:6.0-jammy-chiseled⁠)⁠:117MBubuntu/dotnet-aspnet(mcr.microsoft.com/dotnet/nightly/apsnet:6.0-jammy-chiseled⁠)⁠:140MB丸括弧の中はMicrosoftのレジストリ上のイメージ名です。dotnet-despは、「⁠.NETを動かすための環境」のみ用意されており、.NETのランタイムライブラリは含まれていません。containedな.NETバイナリ群をインストールする必要があります。それに対してdotnet-runtimeとdotnet-apsnetは、それぞれのランタイムライブラリがインストール済みのイメージとなります。よってビルドした.NETバイナリのみをコンテナに取り込めば完成です。これらのイメージは、aptコマンドはもちろんのこと、bashなどのシェルコマンドも同梱されていません。rootアカウントも存在せず、UIDとGIDがそれぞれ101のユーザーで実行することになります。よって実際のDockerイメージを作るには、マルチステージビルドを用いて取り込むことになります。HubのURLでも解説されているため、まずはそちらを参照すると良いでしょう[5]。Chiselを用いて.NET以外の自前のイメージをビルドすることも可能です。Canonicalによくある開発者個人の思いつきと情熱だけで作られているプログラムなので、仕様の安定性とかカスタマイズ性はあまり期待しないほうが良いです。このようにUbuntuでも、CLIアプリケーションやWebアプリケーションであれば、十分に本格的な.NETプログラミングが可能になっています。Codeと組み合わせれば開発手法もWindowsのそれに近くなってきます。GUI部分のサポートがないものの、WindowsとUbuntuの両方で動くCLI/Webアプリケーションを開発する必要がある場合は、.NETも選択肢に含めても良いのではないでしょうか。2022が開催されます。これは韓国でのオフラインおよびオンラインで開催されるカンファレンスで、現在セミナー発表者を募集中です。セミナーは会場に訪れての発表だけでなく、リアルタイムのオンライン発表も可能です。発表の言語や資料が英語である必要はありません。各国から参加される以上、英語のほうが伝わりやすいですが、資料は英語で発表は日本語のような組み合わせも可能です。募集期限は9月14日までです。その後、9月27日まで審査を行い、10月5日までにはその結果を通知し、発表の意志の確認を行うことになるようです。昨年度の内容から、発表の難易度はかなり多種多様なものが許容されるようです。日本からもふるってご応募ください。オフライン開催に伴う旅費補助も検討中で、そのためのスポンサーも随時募集中のようです。Ubuntuにお世話になっている企業の皆様は、ぜひスポンサーのご検討もよろしくお願いいたします。Ltd.ページ内容の全部あるいは一部を無断で利用することを禁止します⁠。個別にライセンスが設定されている記事等はそのライセンスに従います。